summaryrefslogtreecommitdiff
path: root/src/VBox/Main
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main')
-rw-r--r--src/VBox/Main/Docs-Intro.cpp91
-rw-r--r--src/VBox/Main/Makefile.kmk175
-rw-r--r--src/VBox/Main/cbinding/Makefile.kmk17
-rw-r--r--src/VBox/Main/cbinding/VBoxCAPI_v4_1.h7866
-rw-r--r--src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in (renamed from src/VBox/Main/cbinding/VBoxXPCOMCGlue.h)4
-rw-r--r--src/VBox/Main/cbinding/xpcidl.xsl35
-rw-r--r--src/VBox/Main/glue/AutoLock.cpp178
-rw-r--r--src/VBox/Main/glue/ErrorInfo.cpp2
-rw-r--r--src/VBox/Main/glue/VirtualBoxErrorInfo.cpp388
-rw-r--r--src/VBox/Main/glue/com.cpp134
-rw-r--r--src/VBox/Main/glue/constants-python.xsl16
-rw-r--r--src/VBox/Main/glue/errorprint.cpp125
-rw-r--r--src/VBox/Main/glue/glue-java.xsl18
-rw-r--r--src/VBox/Main/glue/string.cpp94
-rw-r--r--src/VBox/Main/glue/tests/TestVBox.java2
-rwxr-xr-x[-rw-r--r--]src/VBox/Main/glue/vboxapi.py23
-rw-r--r--src/VBox/Main/idl/VirtualBox.xidl3437
-rw-r--r--src/VBox/Main/idl/comimpl.xsl60
-rw-r--r--src/VBox/Main/idl/docstrip.xsl18
-rw-r--r--src/VBox/Main/idl/doxygen.xsl18
-rw-r--r--src/VBox/Main/idl/midl.xsl27
-rw-r--r--src/VBox/Main/idl/xpidl.xsl18
-rw-r--r--src/VBox/Main/include/AdditionsFacilityImpl.h1
-rw-r--r--src/VBox/Main/include/ApplianceImpl.h21
-rw-r--r--src/VBox/Main/include/ApplianceImplPrivate.h15
-rw-r--r--src/VBox/Main/include/AutoCaller.h21
-rw-r--r--src/VBox/Main/include/AutostartDb.h95
-rw-r--r--src/VBox/Main/include/BandwidthControlImpl.h10
-rw-r--r--src/VBox/Main/include/BandwidthGroupImpl.h8
-rw-r--r--src/VBox/Main/include/BusAssignmentManager.h32
-rw-r--r--src/VBox/Main/include/ConsoleImpl.h77
-rw-r--r--src/VBox/Main/include/ConsoleVRDPServer.h29
-rw-r--r--src/VBox/Main/include/DisplayImpl.h9
-rw-r--r--src/VBox/Main/include/DisplayUtils.h4
-rw-r--r--src/VBox/Main/include/EventImpl.h4
-rw-r--r--src/VBox/Main/include/ExtPackManagerImpl.h2
-rw-r--r--src/VBox/Main/include/ExtPackUtil.h10
-rw-r--r--src/VBox/Main/include/FramebufferImpl.h8
-rw-r--r--src/VBox/Main/include/Global.h22
-rw-r--r--src/VBox/Main/include/GuestCtrlImplPrivate.h329
-rw-r--r--src/VBox/Main/include/GuestDirEntryImpl.h76
-rw-r--r--src/VBox/Main/include/GuestDirectoryImpl.h82
-rw-r--r--src/VBox/Main/include/GuestDnDImpl.h53
-rw-r--r--src/VBox/Main/include/GuestFileImpl.h96
-rw-r--r--src/VBox/Main/include/GuestFsObjInfoImpl.h85
-rw-r--r--src/VBox/Main/include/GuestImpl.h278
-rw-r--r--src/VBox/Main/include/GuestOSTypeImpl.h36
-rw-r--r--src/VBox/Main/include/GuestProcessImpl.h195
-rw-r--r--src/VBox/Main/include/GuestSessionImpl.h362
-rw-r--r--src/VBox/Main/include/HashedPw.h27
-rw-r--r--src/VBox/Main/include/HostImpl.h3
-rw-r--r--src/VBox/Main/include/HostNetworkInterfaceImpl.h63
-rw-r--r--src/VBox/Main/include/Logging.h5
-rw-r--r--src/VBox/Main/include/MachineDebuggerImpl.h62
-rw-r--r--src/VBox/Main/include/MachineImpl.h206
-rw-r--r--src/VBox/Main/include/MediumAttachmentImpl.h6
-rw-r--r--src/VBox/Main/include/MediumImpl.h32
-rw-r--r--src/VBox/Main/include/NATEngineImpl.h66
-rw-r--r--src/VBox/Main/include/NetworkAdapterImpl.h10
-rw-r--r--src/VBox/Main/include/Nvram.h46
-rw-r--r--src/VBox/Main/include/PCIDeviceAttachmentImpl.h (renamed from src/VBox/Main/include/PciDeviceAttachmentImpl.h)44
-rw-r--r--src/VBox/Main/include/PCIRawDevImpl.h (renamed from src/VBox/Main/include/PciRawDevImpl.h)12
-rw-r--r--src/VBox/Main/include/ParallelPortImpl.h4
-rw-r--r--src/VBox/Main/include/Performance.h257
-rw-r--r--src/VBox/Main/include/PerformanceImpl.h4
-rw-r--r--src/VBox/Main/include/ProgressProxyImpl.h4
-rw-r--r--src/VBox/Main/include/SerialPortImpl.h4
-rw-r--r--src/VBox/Main/include/SessionImpl.h6
-rw-r--r--src/VBox/Main/include/SnapshotImpl.h24
-rw-r--r--src/VBox/Main/include/StorageControllerImpl.h6
-rw-r--r--src/VBox/Main/include/SystemPropertiesImpl.h10
-rw-r--r--src/VBox/Main/include/USBControllerImpl.h46
-rw-r--r--src/VBox/Main/include/USBProxyService.h4
-rw-r--r--src/VBox/Main/include/VirtualBoxBase.h137
-rw-r--r--src/VBox/Main/include/VirtualBoxErrorInfoImpl.h3
-rw-r--r--src/VBox/Main/include/VirtualBoxImpl.h143
-rw-r--r--src/VBox/Main/include/netif.h2
-rw-r--r--src/VBox/Main/src-all/DisplayUtils.cpp50
-rw-r--r--src/VBox/Main/src-all/EventImpl.cpp168
-rw-r--r--src/VBox/Main/src-all/ExtPackManagerImpl.cpp62
-rw-r--r--src/VBox/Main/src-all/ExtPackUtil.cpp2
-rw-r--r--src/VBox/Main/src-all/Global.cpp221
-rw-r--r--src/VBox/Main/src-all/HashedPw.cpp103
-rw-r--r--src/VBox/Main/src-all/PCIDeviceAttachmentImpl.cpp (renamed from src/VBox/Main/src-all/PciDeviceAttachmentImpl.cpp)36
-rw-r--r--src/VBox/Main/src-all/ProgressImpl.cpp20
-rw-r--r--src/VBox/Main/src-all/VirtualBoxBase.cpp261
-rw-r--r--src/VBox/Main/src-all/VirtualBoxErrorInfoImpl.cpp95
-rw-r--r--src/VBox/Main/src-all/win/VirtualBox_rgs.xsl18
-rw-r--r--src/VBox/Main/src-all/win/comregister.cmd127
-rw-r--r--src/VBox/Main/src-client/BusAssignmentManager.cpp98
-rw-r--r--src/VBox/Main/src-client/ConsoleImpl.cpp1416
-rw-r--r--src/VBox/Main/src-client/ConsoleImpl2.cpp709
-rw-r--r--src/VBox/Main/src-client/ConsoleImplTeleporter.cpp21
-rw-r--r--src/VBox/Main/src-client/ConsoleVRDPServer.cpp581
-rw-r--r--src/VBox/Main/src-client/DisplayImpl.cpp526
-rw-r--r--src/VBox/Main/src-client/GuestCtrlIO.cpp441
-rw-r--r--src/VBox/Main/src-client/GuestCtrlImpl.cpp2675
-rw-r--r--src/VBox/Main/src-client/GuestCtrlImplDir.cpp617
-rw-r--r--src/VBox/Main/src-client/GuestCtrlImplFile.cpp246
-rw-r--r--src/VBox/Main/src-client/GuestCtrlImplTasks.cpp1050
-rw-r--r--src/VBox/Main/src-client/GuestCtrlPrivate.cpp1077
-rw-r--r--src/VBox/Main/src-client/GuestDirEntryImpl.cpp155
-rw-r--r--src/VBox/Main/src-client/GuestDirectoryImpl.cpp296
-rw-r--r--src/VBox/Main/src-client/GuestDnDImpl.cpp995
-rw-r--r--src/VBox/Main/src-client/GuestFileImpl.cpp339
-rw-r--r--src/VBox/Main/src-client/GuestFsObjInfoImpl.cpp412
-rw-r--r--src/VBox/Main/src-client/GuestImpl.cpp451
-rw-r--r--src/VBox/Main/src-client/GuestProcessImpl.cpp2136
-rw-r--r--src/VBox/Main/src-client/GuestSessionImpl.cpp2055
-rw-r--r--src/VBox/Main/src-client/GuestSessionImplTasks.cpp1423
-rw-r--r--src/VBox/Main/src-client/HGCM.cpp13
-rw-r--r--src/VBox/Main/src-client/MachineDebuggerImpl.cpp293
-rw-r--r--src/VBox/Main/src-client/MouseImpl.cpp49
-rw-r--r--src/VBox/Main/src-client/Nvram.cpp331
-rw-r--r--src/VBox/Main/src-client/PCIRawDevImpl.cpp (renamed from src/VBox/Main/src-client/PciRawDevImpl.cpp)54
-rw-r--r--src/VBox/Main/src-client/SessionImpl.cpp86
-rw-r--r--src/VBox/Main/src-client/UsbCardReader.cpp74
-rw-r--r--src/VBox/Main/src-client/VBoxDriversRegister.cpp11
-rw-r--r--src/VBox/Main/src-client/VMMDevInterface.cpp3
-rw-r--r--src/VBox/Main/src-client/win/dllmain.cpp2
-rw-r--r--src/VBox/Main/src-client/xpcom/module.cpp30
-rw-r--r--src/VBox/Main/src-helper-apps/VBoxExtPackHelperApp.cpp14
-rw-r--r--src/VBox/Main/src-server/ApplianceImpl.cpp268
-rw-r--r--src/VBox/Main/src-server/ApplianceImplExport.cpp98
-rw-r--r--src/VBox/Main/src-server/ApplianceImplIO.cpp374
-rw-r--r--src/VBox/Main/src-server/ApplianceImplImport.cpp262
-rw-r--r--src/VBox/Main/src-server/BandwidthControlImpl.cpp20
-rw-r--r--src/VBox/Main/src-server/BandwidthGroupImpl.cpp30
-rw-r--r--src/VBox/Main/src-server/DHCPServerRunner.cpp4
-rw-r--r--src/VBox/Main/src-server/GuestOSTypeImpl.cpp126
-rw-r--r--src/VBox/Main/src-server/HostImpl.cpp312
-rw-r--r--src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp158
-rw-r--r--src/VBox/Main/src-server/HostUSBDeviceImpl.cpp233
-rw-r--r--src/VBox/Main/src-server/Logging.cpp133
-rw-r--r--src/VBox/Main/src-server/MachineImpl.cpp2029
-rw-r--r--src/VBox/Main/src-server/MachineImplCloneVM.cpp89
-rw-r--r--src/VBox/Main/src-server/MediumAttachmentImpl.cpp36
-rw-r--r--src/VBox/Main/src-server/MediumImpl.cpp949
-rw-r--r--src/VBox/Main/src-server/NATEngineImpl.cpp140
-rw-r--r--src/VBox/Main/src-server/NetworkAdapterImpl.cpp180
-rw-r--r--src/VBox/Main/src-server/Performance.cpp340
-rw-r--r--src/VBox/Main/src-server/PerformanceImpl.cpp27
-rw-r--r--src/VBox/Main/src-server/SnapshotImpl.cpp275
-rw-r--r--src/VBox/Main/src-server/StorageControllerImpl.cpp10
-rw-r--r--src/VBox/Main/src-server/SystemPropertiesImpl.cpp197
-rw-r--r--src/VBox/Main/src-server/USBControllerImpl.cpp227
-rw-r--r--src/VBox/Main/src-server/USBProxyService.cpp135
-rw-r--r--src/VBox/Main/src-server/VirtualBoxImpl.cpp1403
-rw-r--r--src/VBox/Main/src-server/darwin/USBProxyServiceDarwin.cpp51
-rw-r--r--src/VBox/Main/src-server/darwin/iokit.cpp4
-rw-r--r--src/VBox/Main/src-server/freebsd/NetIf-freebsd.cpp4
-rw-r--r--src/VBox/Main/src-server/freebsd/USBProxyServiceFreeBSD.cpp21
-rw-r--r--src/VBox/Main/src-server/generic/AutostartDb-generic.cpp262
-rw-r--r--src/VBox/Main/src-server/generic/NetIf-generic.cpp76
-rw-r--r--src/VBox/Main/src-server/linux/NetIf-linux.cpp43
-rw-r--r--src/VBox/Main/src-server/linux/PerformanceLinux.cpp310
-rw-r--r--src/VBox/Main/src-server/linux/USBGetDevices.cpp4
-rw-r--r--src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp27
-rw-r--r--src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp70
-rw-r--r--src/VBox/Main/src-server/solaris/NetIf-solaris.cpp71
-rw-r--r--src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp480
-rw-r--r--src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp20
-rw-r--r--src/VBox/Main/src-server/win/NetIf-win.cpp2
-rw-r--r--src/VBox/Main/src-server/win/USBProxyServiceWindows.cpp28
-rw-r--r--src/VBox/Main/src-server/win/svchlp.cpp3
-rw-r--r--src/VBox/Main/src-server/win/svcmain.cpp23
-rw-r--r--src/VBox/Main/src-server/xpcom/server.cpp63
-rw-r--r--src/VBox/Main/testcase/Makefile.kmk31
-rw-r--r--src/VBox/Main/testcase/tstAPI.cpp148
-rw-r--r--src/VBox/Main/testcase/tstCollector.cpp204
-rw-r--r--src/VBox/Main/testcase/tstGuestCtrlContextID.cpp97
-rw-r--r--src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp19
-rw-r--r--src/VBox/Main/testcase/tstOVF.cpp2
-rw-r--r--src/VBox/Main/testcase/tstVBoxAPILinux.cpp6
-rw-r--r--src/VBox/Main/webservice/MANIFEST.MF.in22
-rw-r--r--src/VBox/Main/webservice/Makefile.kmk27
-rw-r--r--src/VBox/Main/webservice/platform-xidl.xsl18
-rwxr-xr-xsrc/VBox/Main/webservice/samples/perl/clienttest.pl103
-rw-r--r--src/VBox/Main/webservice/vboxweb.cpp196
-rw-r--r--src/VBox/Main/webservice/vboxweb.h2
-rw-r--r--src/VBox/Main/webservice/websrv-cpp.xsl142
-rw-r--r--src/VBox/Main/webservice/websrv-nsmap.xsl18
-rw-r--r--src/VBox/Main/webservice/websrv-php.xsl18
-rw-r--r--src/VBox/Main/webservice/websrv-python.xsl18
-rw-r--r--src/VBox/Main/webservice/websrv-shared.inc.xsl24
-rw-r--r--src/VBox/Main/webservice/websrv-typemap.xsl18
-rw-r--r--src/VBox/Main/webservice/websrv-wsdl-service.xsl18
-rw-r--r--src/VBox/Main/webservice/websrv-wsdl.xsl96
-rw-r--r--src/VBox/Main/webservice/websrv-wsdl2gsoapH.xsl18
-rw-r--r--src/VBox/Main/xml/SchemaDefs.xsl71
-rw-r--r--src/VBox/Main/xml/Settings.cpp514
-rw-r--r--src/VBox/Main/xml/SettingsConverter.xsl18
-rw-r--r--src/VBox/Main/xml/VirtualBox-settings-common.xsd139
-rw-r--r--src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd16
-rw-r--r--src/VBox/Main/xml/VirtualBox-settings-linux.xsd16
-rw-r--r--src/VBox/Main/xml/VirtualBox-settings-macosx.xsd16
-rw-r--r--src/VBox/Main/xml/VirtualBox-settings-os2.xsd16
-rw-r--r--src/VBox/Main/xml/VirtualBox-settings-solaris.xsd16
-rw-r--r--src/VBox/Main/xml/VirtualBox-settings-windows.xsd16
-rw-r--r--src/VBox/Main/xml/ovfreader.cpp3
200 files changed, 35097 insertions, 12390 deletions
diff --git a/src/VBox/Main/Docs-Intro.cpp b/src/VBox/Main/Docs-Intro.cpp
new file mode 100644
index 000000000..df647cb89
--- /dev/null
+++ b/src/VBox/Main/Docs-Intro.cpp
@@ -0,0 +1,91 @@
+/* $Id: Docs-Intro.cpp $ */
+/** @file
+ * This file contains the introduction to Main for developers.
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/** @page pg_main Main API
+ *
+ * First of all, check out the "Technical background" chapter in the manual, pay
+ * attention to the "VirtualBox executables and components" chapter. It lists
+ * three processes, (1) VBoxSVC, (2) VirtualBox in manager mode and (3)
+ * VirtualBox in VM mode. This will be referred to as (1) server, (2) client
+ * and (3) VM process, respectively.
+ *
+ *
+ * @section sec_main_walk_thru_suspend IConsole::Pause Walkthru
+ *
+ * The instigator can be a client (VirtualBox in manager mode, VBoxManage
+ * controlvm, web services, ++) or the VM process it self (i.e. you select
+ * pause via the menu or the host key short cut).
+ *
+ * We will not cover the case where the guest triggers a suspend.
+ *
+ * Approximate sequence of events:
+ * - Client calls IConsole::Pause.
+ * - The COM/XPCOM routes this to the VM process, invoking Console::Pause() in
+ * ConsoleImpl.cpp. (The IConsole::Pause method in the client process is a
+ * COM/XPCOM stub method which does marshalling+IPC.)
+ * - Console::Pause validates the Console object state, the VM state and the VM
+ * handle.
+ * - Console::Pause calls VMR3Suspend to do the actual suspending.
+ * - VMR3Suspend() in VMM/VMMR3/VM.cpp calls VMMR3EmtRendezvous() to change the
+ * VM state synchronously on all EMTs (threads performing as virtual CPUs).
+ * - VMMR3EmtRendezvous() will first detect that the caller isn't an EMT and
+ * use VMR3ReqCallWait() to forward the call to an EMT.
+ * - When VMMR3EmtRendezvous() is called again on an EMT, it will signal the
+ * other EMTs by raising a force action flag (VM_FF_EMT_RENDEZVOUS) and then
+ * poke them via VMR3NotifyGlobalFFU(). Then wait for them all to arrive.
+ * - The other EMTs will call VMMR3EmtRendezvousFF as soon as they can.
+ * - When all EMTs are there, the calling back of vmR3Suspend() on each CPU in
+ * decending order will start.
+ * - When the CPU with the higest ID calls vmR3Suspend() the VM state is
+ * changed to VMSTATE_SUSPENDING or VMSTATE_SUSPENDING_EXT_LS.
+ * - When the CPU with ID 0 calls vmR3Suspend() the virtual device emulations
+ * and drivers get notified via PDMR3Suspend().
+ * - PDMR3Suspend() in VMM/VMMR3/PDM.cpp will iterate thru all device
+ * emulations and notify them that the VM is suspending by calling their
+ * PDMDEVREG::pfnSuspend / PDMUSBREG::pfnSuspend entry point (can be NULL).
+ * For each device it will iterate the chains of drivers and call their
+ * PDMDRVREG::pfnSuspend entry point as well.
+ * - Should a worker thread in a PDM device or PDM driver be busy and need some
+ * extra time to finish up / notice the pending suspend, the device or driver
+ * will ask for more time via PDMDevHlpSetAsyncNotification(),
+ * PDMDrvHlpSetAsyncNotification() or PDMUsbHlpSetAsyncNotification().
+ * PDMR3Suspend will then poll these devices and drivers frequently until all
+ * are done.
+ * - PDMR3Suspend() will return to vmR3Suspend() once all PDM devices and PDM
+ * drivers has responded to the pfnSuspend callback.
+ * - The virtual CPU with ID 0 returns from vmR3Suspend() to the rendezvous
+ * code and the EMTs are released.
+ * - The inner VMMR3EmtRendezvous() call returns and this in turn triggers the
+ * VMR3ReqCallWait() call to return (with the status code of the inner call).
+ * - The outer VMMR3EmtRendezvous() returns to VMR3Suspend().
+ * - VMR3Suspend() returns to Console::Pause().
+ * - Console::Pause() checks the result and flags provides error details on
+ * failure.
+ * - Console::Pause() returns to the COM/XPCOM marshalling/IPC stuff.
+ * - Switch back to client process.
+ * - The IConsole::Pause() call returns. The end.
+ *
+ * Summary of above: Client process calls into the VM process, VM process does a
+ * bunch of inter thread calls with all the EMT, EMT0 suspends the PDM devices
+ * and drivers.
+ *
+ * The EMTs will return to the outer execution loop, vmR3EmulationThreadWithId()
+ * in VMM/VMMR3/VMEmt.cpp, where they will mostly do sleep. They will not
+ * execute any guest code until VMR3Resume() is called.
+ *
+ */
+
diff --git a/src/VBox/Main/Makefile.kmk b/src/VBox/Main/Makefile.kmk
index 5a9d0e622..66b9184a7 100644
--- a/src/VBox/Main/Makefile.kmk
+++ b/src/VBox/Main/Makefile.kmk
@@ -4,7 +4,7 @@
#
#
-# Copyright (C) 2006-2011 Oracle Corporation
+# Copyright (C) 2004-2012 Oracle Corporation
#
# This file is part of VirtualBox Open Source Edition (OSE), as
# available from http://www.virtualbox.org. This file is free software;
@@ -37,8 +37,8 @@ ifdef VBOX_ONLY_SDK
# I'm Evil! Dr. Evil.
VBoxCOM_0_OUTDIR = $(PATH_TARGET)/VBoxCOM
BLDDIRS += $(VBoxCOM_0_OUTDIR) $(PATH_STAGE_BIN)/components
- include $(KBUILD_PATH)/tools/VCC70.kmk
- include $(KBUILD_PATH)/sdks/WINPSDK.kmk
+ include $(KBUILD_PATH)/tools/$(VBOX_VCC_TOOL).kmk # For the idl /cpp statement.
+ include $(KBUILD_PATH)/sdks/$(VBOX_WINPSDK).kmk
endif # !VBOX_ONLY_SDK
@@ -57,6 +57,8 @@ VBOX_MAIN_DEFS += \
$(if $(VBOX_WITH_RAW_MODE),VBOX_WITH_RAW_MODE,) \
$(if $(VBOX_WITH_NETFLT),VBOX_WITH_NETFLT,) \
$(if $(VBOX_WITH_COPYTOGUEST),VBOX_WITH_COPYTOGUEST,) \
+ $(if $(VBOX_WITH_DRAG_AND_DROP),VBOX_WITH_DRAG_AND_DROP,) \
+ $(if $(VBOX_WITH_DRAG_AND_DROP_GH),VBOX_WITH_DRAG_AND_DROP_GH,) \
$(if $(VBOX_WITH_CROGL),VBOX_WITH_CROGL,) \
$(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS,) \
$(if $(VBOX_WITH_GUEST_PROPS_RDONLY_GUEST),VBOX_WITH_GUEST_PROPS_RDONLY_GUEST,) \
@@ -64,7 +66,7 @@ VBOX_MAIN_DEFS += \
$(if $(VBOX_WITH_USB_VIDEO),VBOX_WITH_USB_VIDEO,) \
$(if $(VBOX_WITH_USB_CARDREADER),VBOX_WITH_USB_CARDREADER,) \
$(if $(VBOX_WITH_USB_CARDREADER_TEST),VBOX_WITH_USB_CARDREADER_TEST,) \
- $(if $(VBOX_WITH_HOSTNETIF_API),VBOX_WITH_HOSTNETIF_API,)
+ $(if $(VBOX_WITH_HOSTNETIF_API),VBOX_WITH_HOSTNETIF_API,) \
# Unconditionally enable the new semaphore key generation code
VBOX_MAIN_DEFS += VBOX_WITH_NEW_SYS_V_KEYGEN
@@ -78,20 +80,22 @@ VBOX_IDL_HEADER.XPCOM = $(VBOX_PATH_SDK)/bindings/xpcom/include/VirtualBox_XPCO
# The MS COM specific stuff.
if defined(VBOX_ONLY_SDK) || "$(KBUILD_TARGET)" == "win"
OTHERS += \
- $(VBOX_IDL_FILE.MSCOM) \
- $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h \
- $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox.tlb \
- $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c
+ $(VBOX_IDL_FILE.MSCOM)
OTHER_CLEAN += \
- $(VBOX_IDL_FILE.MSCOM) \
- $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h \
- $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox.tlb \
- $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c \
- $(VBoxCOM_0_OUTDIR)/VirtualBox.h \
- $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c \
+ $(VBOX_IDL_FILE.MSCOM)
+
+ INSTALLS += VBox-mscom-bindings-include VBox-mscom-bindings-lib
+ VBox-mscom-bindings-include_INST = $(INST_SDK)bindings/mscom/include/
+ VBox-mscom-bindings-include_MODE = a+r,u+w
+ VBox-mscom-bindings-include_SOURCES = $(VBoxCOM_0_OUTDIR)/VirtualBox.h
+ VBox-mscom-bindings-include_CLEAN = $(VBoxCOM_0_OUTDIR)/VirtualBox.h
+ VBox-mscom-bindings-lib_INST = $(INST_SDK)bindings/mscom/lib/
+ VBox-mscom-bindings-lib_MODE = a+r,u+w
+ VBox-mscom-bindings-lib_SOURCES = $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c \
+ $(VBoxCOM_0_OUTDIR)/VirtualBox.tlb
+ VBox-mscom-bindings-lib_CLEAN = $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c \
$(VBoxCOM_0_OUTDIR)/VirtualBox.tlb
- VBOX_MAIN_PREREQS += $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c
BLDDIRS += $(VBOX_PATH_SDK)/bindings/mscom/idl
endif
@@ -99,9 +103,9 @@ endif
if defined(VBOX_ONLY_SDK) || "$(KBUILD_TARGET)" != "win"
OTHERS += $(VBOX_IDL_FILE.XPCOM) $(VBOX_IDL_TYPELIB.XPCOM) $(VBOX_IDL_HEADER.XPCOM)
OTHER_CLEAN += \
- $(VBOX_IDL_FILE.XPCOM) \
- $(VBOX_IDL_HEADER.XPCOM) \
- $(VBOX_IDL_TYPELIB.XPCOM)
+ $(VBOX_IDL_FILE.XPCOM) \
+ $(VBOX_IDL_HEADER.XPCOM) \
+ $(VBOX_IDL_TYPELIB.XPCOM)
VBOX_MAIN_PREREQS += $(VBOX_IDL_TYPELIB.XPCOM) $(VBOX_IDL_HEADER.XPCOM)
BLDDIRS += \
@@ -171,9 +175,9 @@ VBox-python-glue_INST = $(INST_SDK)installer/vboxapi/
VBox-python-glue_MODE = a+r,u+w
VBox-python-glue_SOURCES = \
glue/vboxapi.py=>__init__.py \
- $(VBox-python-glue_0_OUTDIR)/VirtualBox_constants.py
+ $(VBox-python-glue_0_OUTDIR)/VirtualBox_constants.py
VBox-python-glue_CLEAN = \
- $(VBox-python-glue_0_OUTDIR)/VirtualBox_constants.py
+ $(VBox-python-glue_0_OUTDIR)/VirtualBox_constants.py
$$(VBox-python-glue_0_OUTDIR)/VirtualBox_constants.py: \
$(VBOX_PATH_MAIN_SRC)/glue/constants-python.xsl \
@@ -195,7 +199,7 @@ VBOX_XML_SCHEMADEFS_H = $(PATH_TARGET)/Main/SchemaDefs.h
VBOX_XML_SCHEMADEFS_CPP = $(PATH_TARGET)/Main/SchemaDefs.cpp
VBOX_XML_SCHEMADEFS_XSL = $(VBOX_PATH_MAIN_SRC)/xml/SchemaDefs.xsl
-VBOX_AUTOGEN_EVENT_H = $(PATH_TARGET)/Main/VBoxEvents.h
+VBOX_AUTOGEN_EVENT_H = $(PATH_TARGET)/Main/VBoxEvents.h
VBOX_AUTOGEN_EVENT_CPP = $(PATH_TARGET)/Main/VBoxEvents.cpp
testschemadefs: $(VBOX_XML_SCHEMADEFS_H) $(VBOX_XML_SCHEMADEFS_CPP)
@@ -213,7 +217,6 @@ VBoxSVC_DEFS = \
$(if $(VBOX_WITH_VBOXSDL),VBOX_WITH_VBOXSDL,) \
$(if $(VBOX_WITH_HEADLESS),VBOX_WITH_HEADLESS,) \
$(if $(VBOX_WITH_QTGUI),VBOX_WITH_QTGUI,) \
- $(if $(VBOX_WITH_COCOA_QT),VBOX_WITH_COCOA_QT,) \
$(if $(VBOX_WITH_HGCM),VBOX_WITH_HGCM,) \
$(if $(VBOX_WITH_ALSA),VBOX_WITH_ALSA,) \
$(if $(VBOX_WITH_PULSE),VBOX_WITH_PULSE,) \
@@ -241,8 +244,7 @@ ifdef VBOX_WITH_USB
$(if $(VBOX_WITH_NEW_USB_CODE_ON_DARWIN),VBOX_WITH_NEW_USB_CODE_ON_DARWIN,)
endif
VBoxSVC_DEFS.win += VBOX_COM_OUTOFPROC_MODULE
-VBoxSVC_DEFS.win.x86 += _WIN32_WINNT=0x0500
-VBoxSVC_DEFS.win.amd64 += _WIN32_WINNT=0x0510
+VBoxSVC_DEFS.win += _WIN32_WINNT=0x0510
# Try to load and use libhal at runtime for probing removable media
# VBoxSVC_DEFS.linux += VBOX_USE_LIBHAL
VBoxSVC_DEFS.solaris += VBOX_USE_LIBHAL
@@ -271,8 +273,8 @@ VBoxSVC_LIBS.solaris = \
nsl \
devinfo \
socket \
- $(LIB_VMM)
-
+ $(LIB_VMM)
+
VBoxSVC_INTERMEDIATES = \
$(VBOX_MAIN_PREREQS) \
$(VBOX_XML_SCHEMADEFS_H) \
@@ -284,8 +286,9 @@ VBoxSVC_SOURCES = \
src-all/DisplayUtils.cpp \
src-all/EventImpl.cpp \
src-all/Global.cpp \
+ src-all/HashedPw.cpp \
src-all/Logging.cpp \
- src-all/PciDeviceAttachmentImpl.cpp \
+ src-all/PCIDeviceAttachmentImpl.cpp \
src-all/ProgressImpl.cpp \
src-all/SharedFolderImpl.cpp \
src-all/VirtualBoxBase.cpp \
@@ -305,7 +308,6 @@ VBoxSVC_SOURCES = \
src-server/HostImpl.cpp \
src-server/HostNetworkInterfaceImpl.cpp \
src-server/HostPower.cpp \
- src-server/Logging.cpp \
src-server/MachineImpl.cpp \
src-server/MachineImplCloneVM.cpp \
src-server/Matching.cpp \
@@ -313,6 +315,7 @@ VBoxSVC_SOURCES = \
src-server/MediumFormatImpl.cpp \
src-server/MediumImpl.cpp \
src-server/MediumLock.cpp \
+ $(if $(VBOX_WITH_NAT_SERVICE),src-server/NATServerImpl.cpp,) \
src-server/NATEngineImpl.cpp \
src-server/NetworkAdapterImpl.cpp \
src-server/ParallelPortImpl.cpp \
@@ -325,6 +328,7 @@ VBoxSVC_SOURCES = \
src-server/VFSExplorerImpl.cpp \
src-server/VirtualBoxImpl.cpp \
src-server/VRDEServerImpl.cpp \
+ src-server/generic/AutostartDb-generic.cpp \
xml/ovfreader.cpp \
xml/Settings.cpp \
$(VBOX_XML_SCHEMADEFS_CPP) \
@@ -340,7 +344,7 @@ VBoxSVC_SOURCES.win = \
src-server/win/svchlp.cpp \
src-server/win/HostPowerWin.cpp \
src-server/win/VBoxSVC.rc \
- src-server/win/VBoxComEvents.cpp
+ src-server/win/VBoxComEvents.cpp
VBoxSVC_SOURCES.linux = \
src-server/linux/HostHardwareLinux.cpp
@@ -352,10 +356,6 @@ VBoxSVC_SOURCES.solaris = \
VBoxSVC_SOURCES.freebsd = \
src-server/freebsd/HostHardwareFreeBSD.cpp
-src-server/Logging.cpp_DEFS = \
- VBOX_BUILD_TARGET=\"$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)\" \
- $(if $(VBOX_BLEEDING_EDGE),VBOX_BLEEDING_EDGE=\"$(VBOX_BLEEDING_EDGE)\",)
-
ifdef VBOX_WITH_USB
ifdef VBOX_WITH_SYSFS_BY_DEFAULT
@@ -375,17 +375,12 @@ ifdef VBOX_WITH_USB
endif
ifdef VBOX_WITH_NETFLT
- # Note! The includes from the TOOL has lower priority than the SDKs,
- # since comdef.h is in both the DDK and VCC we want to make sure
- # we're using the VCC since we're not using the DDK compiler/crt.
- # Since this is potentially risky, restrict it to the source file
- # needing it.
- src-server/win/NetIf-win.cpp_INCS.win += $(PATH_TOOL_$(VBOX_VCC_TOOL)_INC)
VBoxSVC_LIBS.win += \
$(PATH_STAGE_LIB)/WinNetConfig$(VBOX_SUFF_LIB) \
$(PATH_STAGE_LIB)/VBoxDrvCfg$(VBOX_SUFF_LIB) \
+ $(PATH_SDK_$(VBOX_WINDDK)_LIB)/Newdev.lib \
$(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \
- $(PATH_SDK_WINPSDK_LIB)/WbemUuid.Lib
+ $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/WbemUuid.Lib
endif
VBoxSVC_LDFLAGS.darwin = -framework IOKit -framework SystemConfiguration
@@ -409,7 +404,7 @@ ifdef VBOX_WITH_RESOURCE_USAGE_API
VBoxSVC_SOURCES.solaris += src-server/solaris/PerformanceSolaris.cpp
VBoxSVC_SOURCES.win += src-server/win/PerformanceWin.cpp
VBoxSVC_LDFLAGS.darwin += -lproc
- VBoxSVC_LDFLAGS.solaris += -lkstat
+ VBoxSVC_LDFLAGS.solaris += -lkstat -lnvpair
VBoxSVC_LDFLAGS.win += psapi.lib powrprof.lib
endif
@@ -522,7 +517,6 @@ endif # VBOX_WITH_XPCOM
#
DLLS += VBoxC
VBoxC_TEMPLATE = VBOXMAINCOMP
-VBoxC_SDKS = VBOX_LIBPNG VBOX_ZLIB
VBoxC_DEFS = \
IN_RING3 \
$(VBOX_MAIN_DEFS) \
@@ -533,7 +527,6 @@ VBoxC_DEFS = \
$(if $(VBOX_WITH_PULSE),VBOX_WITH_PULSE,) \
$(if $(VBOX_WITH_WINMM),VBOX_WITH_WINMM,) \
$(if $(VBOX_WITH_SOLARIS_OSS),VBOX_WITH_SOLARIS_OSS,) \
- $(if $(VBOX_WITH_CROSSBOW),VBOX_WITH_CROSSBOW,) \
$(if $(VBOX_WITH_E1000),VBOX_WITH_E1000,) \
$(if $(VBOX_WITH_VIRTIO),VBOX_WITH_VIRTIO,) \
$(if $(VBOX_WITH_EFI),VBOX_WITH_EFI,) \
@@ -542,15 +535,24 @@ VBoxC_DEFS = \
$(if $(VBOX_WITH_VUSB),VBOX_WITH_VUSB,) \
$(if $(VBOX_WITH_HGSMI),VBOX_WITH_HGSMI,) \
$(if $(VBOX_WITH_VIDEOHWACCEL),VBOX_WITH_VIDEOHWACCEL,) \
+ $(if $(VBOX_WITH_DRAG_AND_DROP),VBOX_WITH_DRAG_AND_DROP,) \
+ $(if $(VBOX_WITH_DRAG_AND_DROP_GH),VBOX_WITH_DRAG_AND_DROP_GH,) \
$(if $(VBOX_WITH_USB),VBOX_WITH_USB,) \
$(if-expr defined(VBOX_WITH_EHCI) && defined(VBOX_WITH_USB),VBOX_WITH_EHCI,) \
$(if $(VBOX_WITH_EXTPACK),VBOX_WITH_EXTPACK,) \
- $(if $(VBOX_WITH_PCI_PASSTHROUGH),VBOX_WITH_PCI_PASSTHROUGH,)
+ $(if $(VBOX_WITH_PCI_PASSTHROUGH),VBOX_WITH_PCI_PASSTHROUGH,) \
+ $(if $(VBOX_WITH_VPX),VBOX_WITH_VPX,)
VBoxC_DEFS.darwin.x86 = VBOX_WITH_2X_4GB_ADDR_SPACE
VBoxC_DEFS.win.x86 += _WIN32_WINNT=0x0500
VBoxC_DEFS.win.amd64 += _WIN32_WINNT=0x0510
+ifdef VBOX_WITH_VPX
+ VBoxC_SDKS = VBOX_LIBPNG VBOX_ZLIB VBOX_VPX
+else
+ VBoxC_SDKS = VBOX_LIBPNG VBOX_ZLIB
+endif
+
VBoxC_INCS = \
include \
$(VBoxC_0_OUTDIR) \
@@ -563,9 +565,7 @@ VBoxC_LDFLAGS.darwin = \
-install_name $(VBOX_DYLD_EXECUTABLE_PATH)/components/VBoxC.dylib \
-exported_symbols_list $(VBoxC_0_OUTDIR)/VBoxC.def \
-framework IOKit
-ifdef VBOX_USE_VCC80
- VBoxC_LDFLAGS.win = /MANIFEST
-endif
+VBoxC_LDFLAGS.win += /DELAYLOAD:VBoxVMM.dll /MANIFEST
VBoxC_LIBS += \
$(LIB_VMM) \
@@ -573,10 +573,12 @@ VBoxC_LIBS += \
ifdef VBOX_WITH_NETFLT
VBoxC_LIBS.win += \
- $(PATH_STAGE_LIB)/VBoxDrvCfg$(VBOX_SUFF_LIB) \
- $(PATH_STAGE_LIB)/WinNetConfig$(VBOX_SUFF_LIB) \
- $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \
- $(PATH_SDK_WINPSDK_LIB)/WbemUuid.Lib
+ $(PATH_STAGE_LIB)/VBoxDrvCfg$(VBOX_SUFF_LIB) \
+ $(PATH_SDK_$(VBOX_WINDDK)_LIB)/Newdev.lib \
+ $(PATH_STAGE_LIB)/WinNetConfig$(VBOX_SUFF_LIB) \
+ $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \
+ $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/WbemUuid.Lib \
+ $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/delayimp.lib
endif
ifdef VBOX_WITH_CROGL
@@ -596,8 +598,9 @@ VBoxC_SOURCES = \
src-all/DisplayUtils.cpp \
src-all/EventImpl.cpp \
src-all/Global.cpp \
+ src-all/HashedPw.cpp \
src-all/Logging.cpp \
- src-all/PciDeviceAttachmentImpl.cpp \
+ src-all/PCIDeviceAttachmentImpl.cpp \
src-all/ProgressImpl.cpp \
src-all/SharedFolderImpl.cpp \
src-all/VirtualBoxBase.cpp \
@@ -605,20 +608,23 @@ VBoxC_SOURCES = \
$(if $(VBOX_WITH_EXTPACK),src-all/ExtPackManagerImpl.cpp src-all/ExtPackUtil.cpp,) \
$(if $(VBOX_WITH_USB_VIDEO),src-client/UsbWebcamInterface.cpp,) \
$(if $(VBOX_WITH_USB_CARDREADER),src-client/UsbCardReader.cpp,) \
+ src-client/Nvram.cpp \
src-client/AdditionsFacilityImpl.cpp \
src-client/AudioSnifferInterface.cpp \
src-client/BusAssignmentManager.cpp \
- $(if $(VBOX_WITH_PCI_PASSTHROUGH),src-client/PciRawDevImpl.cpp,) \
+ $(if $(VBOX_WITH_PCI_PASSTHROUGH),src-client/PCIRawDevImpl.cpp,) \
src-client/ConsoleImpl.cpp \
src-client/ConsoleImpl2.cpp \
src-client/ConsoleImplTeleporter.cpp \
src-client/ConsoleVRDPServer.cpp \
src-client/DisplayImpl.cpp \
src-client/GuestImpl.cpp \
+ src-client/GuestDirectoryImpl.cpp \
+ src-client/GuestFileImpl.cpp \
+ src-client/GuestFsObjInfoImpl.cpp \
+ src-client/GuestProcessImpl.cpp \
+ src-client/GuestSessionImpl.cpp \
src-client/GuestCtrlImpl.cpp \
- src-client/GuestCtrlIO.cpp \
- src-client/GuestCtrlImplDir.cpp \
- src-client/GuestCtrlImplFile.cpp \
src-client/KeyboardImpl.cpp \
src-client/MachineDebuggerImpl.cpp \
src-client/MouseImpl.cpp \
@@ -637,8 +643,13 @@ VBoxC_SOURCES.win = \
ifdef VBOX_WITH_GUEST_CONTROL
VBoxC_SOURCES += \
- src-client/GuestCtrlImplTasks.cpp \
- src-client/GuestDirEntryImpl.cpp
+ src-client/GuestSessionImplTasks.cpp \
+ src-client/GuestCtrlPrivate.cpp
+endif
+
+ifdef VBOX_WITH_DRAG_AND_DROP
+VBoxC_SOURCES += \
+ src-client/GuestDnDImpl.cpp
endif
ifdef VBOX_WITH_XPCOM
@@ -662,6 +673,16 @@ VBoxC_SOURCES += \
src-client/RemoteUSBBackend.cpp
endif
+ifdef VBOX_WITH_VPX
+VBoxC_SOURCES += \
+ src-client/EbmlWriter.cpp \
+ src-client/VideoRec.cpp
+endif
+
+ifdef VBOX_WITH_NETSHAPER
+VBoxC_DEFS += VBOX_WITH_NETSHAPER
+endif
+
ifeq ($(KBUILD_TARGET),darwin)
VBoxC_ORDERDEPS += $(VBoxC_0_OUTDIR)/VBoxC.def
VBoxC_CLEAN += $(VBoxC_0_OUTDIR)/VBoxC.def
@@ -672,7 +693,6 @@ $$(VBoxC_0_OUTDIR)/VBoxC.def: $(MAKEFILE_CURRENT)
endif
src-client/ConsoleImpl.cpp_DEFS = \
- VBOX_BUILD_TARGET=\"$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)\" \
$(if $(VBOX_BLEEDING_EDGE),VBOX_BLEEDING_EDGE=\"$(VBOX_BLEEDING_EDGE)\",)
@@ -696,8 +716,7 @@ VBoxCOM_SOURCES = \
glue/AutoLock.cpp \
glue/EventQueue.cpp \
glue/ErrorInfo.cpp \
- glue/errorprint.cpp \
- glue/VirtualBoxErrorInfo.cpp
+ glue/errorprint.cpp
VBoxCOM_INCS += \
include
ifeq ($(KBUILD_TARGET),win)
@@ -710,6 +729,9 @@ else # !win
glue/xpcom/helpers.cpp
endif # !win
+glue/com.cpp_DEFS = \
+ $(if $(VBOX_BLEEDING_EDGE),VBOX_BLEEDING_EDGE=\"$(VBOX_BLEEDING_EDGE)\",)
+
#
# The VBoxExtPackHelperApp.
@@ -723,7 +745,7 @@ ifdef VBOX_WITH_EXTPACK
src-helper-apps/VBoxExtPackHelperApp.cpp \
src-all/ExtPackUtil.cpp
VBoxExtPackHelperApp_LIBS = \
- $(LIB_RUNTIME)
+ $(LIB_RUNTIME)
endif # VBOX_WITH_EXTPACK
@@ -755,7 +777,7 @@ endif
# generate rules
-include $(KBUILD_PATH)/subfooter.kmk
+include $(FILE_KBUILD_SUB_FOOTER)
@@ -780,14 +802,6 @@ $(VBOX_IDL_HEADER.XPCOM): $(VBOX_IDL_FILE.XPCOM) | $$(dir $$@) $(VBOX_XPIDL)
$(call MSG_TOOL,xpidl,VBoxSVC,$<,$@)
$(QUIET)$(VBOX_XPIDL_ENV)$(VBOX_XPIDL) -m header -I $(VBOX_PATH_XPCOM_IDL) -e $@ $<
-
-VBOX_MAIN_IDL ?= $(EXEC_X86_WIN32) $(call VBOX_FN_MAKE_WIN_PATH,$(firstword $(wildcard \
- $(PATH_SDK_WINPSDK_BIN)/Midl.Exe\
- $(PATH_SDK_WINPSDK)/Bin/Midl.Exe\
- $(PATH_DEVTOOLS)/win.x86/bin/midl.exe\
- ) Sorry_Cannot_Find_The_Midl_Compiler_In_The_PSDK))
-IDL_DEFS = /nologo
-
$(VBOX_IDL_FILE.MSCOM): $(VBOX_PATH_MAIN_SRC)/idl/midl.xsl $(VBOX_XIDL_FILE) | $$(dir $$@)
$(call MSG_TOOL,xsltproc,VBoxSVC,$<,$@)
$(QUIET)$(VBOX_XSLTPROC) -o $@ $< $(VBOX_XIDL_FILE)
@@ -801,28 +815,15 @@ testidl: $(VBOX_IDL_FILE.MSCOM) $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c
endif
-## @todo r=bird: last changes to this rule showed incorrect dependencies here as it broke testcase (see testboxwin2).
-# This is kind of obvious when looking at the rule, because it's (a) not specifying all it output
-# and (b) generating more stuff *after* the main target has been completed.
-#
-# What needs to be done is to not depend on _i.c in the object subdir, but on all the final outputs.
$(VBoxCOM_0_OUTDIR)/VirtualBox_i.c \
-+ $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox_i.c \
+ $(VBoxCOM_0_OUTDIR)/VirtualBox.h \
-+ $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h \
-+ $(VBoxCOM_0_OUTDIR)/VirtualBox.tlb \
-+ $(VBOX_PATH_SDK)/bindings/mscom/lib/VirtualBox.tlb: $(VBOX_IDL_FILE.MSCOM) | $$(dir $$@)
- $(VBOX_MAIN_IDL) $(IDL_DEFS) \
++ $(VBoxCOM_0_OUTDIR)/VirtualBox.tlb: $(VBOX_IDL_FILE.MSCOM) | $$(dir $$@)
+ $(VBOX_WIN_MIDL) /nologo \
/out $(call VBOX_FN_MAKE_WIN_PATH,$(VBoxCOM_0_OUTDIR)) \
/cpp_cmd $(subst $(EXEC_X86_WIN32),,$(call VBOX_FN_MAKE_WIN_PATH,$(TOOL_$(VBOX_VCC_TOOL)_CC))) \
- /I $(call VBOX_FN_MAKE_WIN_PATH,$(PATH_SDK_WINPSDK_INC)) \
+ /I $(call VBOX_FN_MAKE_WIN_PATH,$(PATH_SDK_$(VBOX_WINPSDK)_INC)) \
/I idl \
$(call VBOX_FN_MAKE_WIN_PATH,$<)
- $(MKDIR) -p $(VBOX_PATH_SDK)/bindings/mscom/include
- $(CP) $(VBoxCOM_0_OUTDIR)/VirtualBox.h $(VBOX_PATH_SDK)/bindings/mscom/include
- $(MKDIR) -p $(VBOX_PATH_SDK)/bindings/mscom/lib
- $(CP) $(VBoxCOM_0_OUTDIR)/VirtualBox.tlb $(VBOX_PATH_SDK)/bindings/mscom/lib
- $(CP) $(VBoxCOM_0_OUTDIR)/VirtualBox_i.c $(VBOX_PATH_SDK)/bindings/mscom/lib
#
# Translation stuff
diff --git a/src/VBox/Main/cbinding/Makefile.kmk b/src/VBox/Main/cbinding/Makefile.kmk
index d2e095b02..7e64c372f 100644
--- a/src/VBox/Main/cbinding/Makefile.kmk
+++ b/src/VBox/Main/cbinding/Makefile.kmk
@@ -38,7 +38,7 @@ XpComCGlue_INST = \
$(INST_SDK)bindings/xpcom/cbinding/
XpComCGlue_SOURCES = \
VBoxXPCOMCGlue.c \
- VBoxXPCOMCGlue.h
+ $(XpComCHeaders_0_OUTDIR)/VBoxXPCOMCGlue.h
INSTALLS += XpComCHeaders
XpComCHeaders_MODE = a+r,u+rw
@@ -49,8 +49,18 @@ XpComCHeaders_SOURCES = \
VBoxCAPI_v3_1.h \
VBoxCAPI_v3_2.h \
VBoxCAPI_v4_0.h \
+ VBoxCAPI_v4_1.h \
$(XpComCHeaders_0_OUTDIR)/VBoxCAPI.h=>VBoxCAPI_v$(VBOX_API_VERSION).h
+$$(XpComCHeaders_0_OUTDIR)/VBoxXPCOMCGlue.h: \
+ $(PATH_SUB_CURRENT)/VBoxXPCOMCGlue.h.in \
+ $(MAKEFILE_CURRENT) \
+ | $$(dir $$@)
+ $(call MSG_GENERATE,,$@)
+ $(QUIET)$(SED) \
+ -e 's/@VBOX_API_VERSION@/$(VBOX_API_VERSION)/' \
+ < $< > $@
+
$$(XpComCHeaders_0_OUTDIR)/VBoxCAPI.h: \
$(PATH_SUB_CURRENT)/xpcidl.xsl \
$(VBOX_XIDL_FILE) \
@@ -98,7 +108,8 @@ if !defined(VBOX_ONLY_SDK) && defined(VBOX_WITH_XPCOM)
PROGRAMS += tstXPCOMCGlue
tstXPCOMCGlue_TEMPLATE = VBOXR3EXE
tstXPCOMCGlue_INCS = \
- $(VBOX_PATH_SDK)/bindings/xpcom/include
+ $(VBOX_PATH_SDK)/bindings/xpcom/include \
+ $(VBOX_PATH_SDK)/bindings/xpcom/cbinding
tstXPCOMCGlue_INTERMEDIATES = \
$(VBOX_PATH_SDK)/bindings/xpcom/cbinding/VBoxXPCOMCGlue.h \
$(VBOX_PATH_SDK)/bindings/xpcom/include/VBoxCAPI_v$(VBOX_API_VERSION).h
@@ -127,5 +138,5 @@ if !defined(VBOX_ONLY_SDK) && defined(VBOX_WITH_XPCOM)
endif # ! VBOX_ONLY_SDK
# generate rules.
-include $(KBUILD_PATH)/subfooter.kmk
+include $(FILE_KBUILD_SUB_FOOTER)
diff --git a/src/VBox/Main/cbinding/VBoxCAPI_v4_1.h b/src/VBox/Main/cbinding/VBoxCAPI_v4_1.h
new file mode 100644
index 000000000..0edd97382
--- /dev/null
+++ b/src/VBox/Main/cbinding/VBoxCAPI_v4_1.h
@@ -0,0 +1,7866 @@
+
+/*
+ * DO NOT EDIT! This is a generated file.
+ *
+ * XPCOM IDL (XPIDL) definition for VirtualBox Main API (COM interfaces)
+ * generated from XIDL (XML interface definition).
+ *
+ * Source : src/VBox/Main/idl/VirtualBox.xidl
+ * Generator : src/VBox/Main/idl/xpcidl.xsl
+ *
+ * This file contains portions from the following Mozilla XPCOM files:
+ * xpcom/include/xpcom/nsID.h
+ * xpcom/include/nsIException.h
+ * xpcom/include/nsprpub/prtypes.h
+ * xpcom/include/xpcom/nsISupportsBase.h
+ *
+ * These files were originally triple-licensed (MPL/GPL2/LGPL2.1). Oracle
+ * elects to distribute this derived work under the LGPL2.1 only.
+ */
+
+/*
+ * Copyright (C) 2008-2012 Oracle Corporation
+ *
+ * This file is part of a free software library; you can redistribute
+ * it and/or modify it under the terms of the GNU Lesser General
+ * Public License version 2.1 as published by the Free Software
+ * Foundation and shipped in the "COPYING" file with this library.
+ * The library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY of any kind.
+ *
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if
+ * any license choice other than GPL or LGPL is available it will
+ * apply instead, Oracle elects to use only the Lesser General Public
+ * License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the
+ * language indicating that LGPLv2 or any later version may be used,
+ * or where a choice of which version of the LGPL is applied is
+ * otherwise unspecified.
+ */
+
+#ifndef ___VirtualBox_CXPCOM_h
+#define ___VirtualBox_CXPCOM_h
+
+#ifdef __cplusplus
+# include "VirtualBox_XPCOM.h"
+#else /* !__cplusplus */
+
+#include <stddef.h>
+#include "wchar.h"
+
+#if defined(WIN32)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) __declspec(dllimport) __type
+#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_BEOS)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(WIN16)
+
+#define PR_CALLBACK_DECL __cdecl
+
+#if defined(_WINDLL)
+#define PR_EXPORT(__type) extern __type _cdecl _export _loadds
+#define PR_IMPORT(__type) extern __type _cdecl _export _loadds
+#define PR_EXPORT_DATA(__type) extern __type _export
+#define PR_IMPORT_DATA(__type) extern __type _export
+
+#define PR_EXTERN(__type) extern __type _cdecl _export _loadds
+#define PR_IMPLEMENT(__type) __type _cdecl _export _loadds
+#define PR_EXTERN_DATA(__type) extern __type _export
+#define PR_IMPLEMENT_DATA(__type) __type _export
+
+#define PR_CALLBACK __cdecl __loadds
+#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK
+
+#else /* this must be .EXE */
+#define PR_EXPORT(__type) extern __type _cdecl _export
+#define PR_IMPORT(__type) extern __type _cdecl _export
+#define PR_EXPORT_DATA(__type) extern __type _export
+#define PR_IMPORT_DATA(__type) extern __type _export
+
+#define PR_EXTERN(__type) extern __type _cdecl _export
+#define PR_IMPLEMENT(__type) __type _cdecl _export
+#define PR_EXTERN_DATA(__type) extern __type _export
+#define PR_IMPLEMENT_DATA(__type) __type _export
+
+#define PR_CALLBACK __cdecl __loadds
+#define PR_STATIC_CALLBACK(__x) __x PR_CALLBACK
+#endif /* _WINDLL */
+
+#elif defined(XP_MAC)
+
+#define PR_EXPORT(__type) extern __declspec(export) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(export) __type
+#define PR_IMPORT(__type) extern __declspec(export) __type
+#define PR_IMPORT_DATA(__type) extern __declspec(export) __type
+
+#define PR_EXTERN(__type) extern __declspec(export) __type
+#define PR_IMPLEMENT(__type) __declspec(export) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(export) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(export) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_OS2) && defined(__declspec)
+
+#define PR_EXPORT(__type) extern __declspec(dllexport) __type
+#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPORT(__type) __declspec(dllimport) __type
+#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type
+
+#define PR_EXTERN(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
+#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
+
+#define PR_CALLBACK
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x
+
+#elif defined(XP_OS2_VACPP)
+
+#define PR_EXPORT(__type) extern __type
+#define PR_EXPORT_DATA(__type) extern __type
+#define PR_IMPORT(__type) extern __type
+#define PR_IMPORT_DATA(__type) extern __type
+
+#define PR_EXTERN(__type) extern __type
+#define PR_IMPLEMENT(__type) __type
+#define PR_EXTERN_DATA(__type) extern __type
+#define PR_IMPLEMENT_DATA(__type) __type
+#define PR_CALLBACK _Optlink
+#define PR_CALLBACK_DECL
+#define PR_STATIC_CALLBACK(__x) static __x PR_CALLBACK
+
+#else /* Unix */
+
+# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+# define PR_EXPORT(__type) __attribute__((visibility("default"))) extern __type
+# define PR_EXPORT_DATA(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPORT(__type) extern __type
+# define PR_IMPORT_DATA(__type) extern __type
+# define PR_EXTERN(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPLEMENT(__type) __attribute__((visibility("default"))) __type
+# define PR_EXTERN_DATA(__type) __attribute__((visibility("default"))) extern __type
+# define PR_IMPLEMENT_DATA(__type) __attribute__((visibility("default"))) __type
+# define PR_CALLBACK
+# define PR_CALLBACK_DECL
+# define PR_STATIC_CALLBACK(__x) static __x
+# else
+# define PR_EXPORT(__type) extern __type
+# define PR_EXPORT_DATA(__type) extern __type
+# define PR_IMPORT(__type) extern __type
+# define PR_IMPORT_DATA(__type) extern __type
+# define PR_EXTERN(__type) extern __type
+# define PR_IMPLEMENT(__type) __type
+# define PR_EXTERN_DATA(__type) extern __type
+# define PR_IMPLEMENT_DATA(__type) __type
+# define PR_CALLBACK
+# define PR_CALLBACK_DECL
+# define PR_STATIC_CALLBACK(__x) static __x
+# endif
+#endif
+
+#if defined(_NSPR_BUILD_)
+#define NSPR_API(__type) PR_EXPORT(__type)
+#define NSPR_DATA_API(__type) PR_EXPORT_DATA(__type)
+#else
+#define NSPR_API(__type) PR_IMPORT(__type)
+#define NSPR_DATA_API(__type) PR_IMPORT_DATA(__type)
+#endif
+
+typedef unsigned char PRUint8;
+#if (defined(HPUX) && defined(__cplusplus) \
+ && !defined(__GNUC__) && __cplusplus < 199707L) \
+ || (defined(SCO) && defined(__cplusplus) \
+ && !defined(__GNUC__) && __cplusplus == 1L)
+typedef char PRInt8;
+#else
+typedef signed char PRInt8;
+#endif
+
+#define PR_INT8_MAX 127
+#define PR_INT8_MIN (-128)
+#define PR_UINT8_MAX 255U
+
+typedef unsigned short PRUint16;
+typedef short PRInt16;
+
+#define PR_INT16_MAX 32767
+#define PR_INT16_MIN (-32768)
+#define PR_UINT16_MAX 65535U
+
+typedef unsigned int PRUint32;
+typedef int PRInt32;
+#define PR_INT32(x) x
+#define PR_UINT32(x) x ## U
+
+#define PR_INT32_MAX PR_INT32(2147483647)
+#define PR_INT32_MIN (-PR_INT32_MAX - 1)
+#define PR_UINT32_MAX PR_UINT32(4294967295)
+
+typedef long PRInt64;
+typedef unsigned long PRUint64;
+typedef int PRIntn;
+typedef unsigned int PRUintn;
+
+typedef double PRFloat64;
+typedef size_t PRSize;
+
+typedef ptrdiff_t PRPtrdiff;
+
+typedef unsigned long PRUptrdiff;
+
+typedef PRIntn PRBool;
+
+#define PR_TRUE 1
+#define PR_FALSE 0
+
+typedef PRUint8 PRPackedBool;
+
+/*
+** Status code used by some routines that have a single point of failure or
+** special status return.
+*/
+typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
+
+#ifndef __PRUNICHAR__
+#define __PRUNICHAR__
+#if defined(WIN32) || defined(XP_MAC)
+typedef wchar_t PRUnichar;
+#else
+typedef PRUint16 PRUnichar;
+#endif
+#endif
+
+typedef long PRWord;
+typedef unsigned long PRUword;
+
+#define nsnull 0
+typedef PRUint32 nsresult;
+
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define NS_LIKELY(x) (__builtin_expect((x), 1))
+#define NS_UNLIKELY(x) (__builtin_expect((x), 0))
+#else
+#define NS_LIKELY(x) (x)
+#define NS_UNLIKELY(x) (x)
+#endif
+
+#define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000))
+#define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000)))
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PR_IntervalNow VBoxNsprPR_IntervalNow
+# define PR_TicksPerSecond VBoxNsprPR_TicksPerSecond
+# define PR_SecondsToInterval VBoxNsprPR_SecondsToInterval
+# define PR_MillisecondsToInterval VBoxNsprPR_MillisecondsToInterval
+# define PR_MicrosecondsToInterval VBoxNsprPR_MicrosecondsToInterval
+# define PR_IntervalToSeconds VBoxNsprPR_IntervalToSeconds
+# define PR_IntervalToMilliseconds VBoxNsprPR_IntervalToMilliseconds
+# define PR_IntervalToMicroseconds VBoxNsprPR_IntervalToMicroseconds
+# define PR_EnterMonitor VBoxNsprPR_EnterMonitor
+# define PR_ExitMonitor VBoxNsprPR_ExitMonitor
+# define PR_Notify VBoxNsprPR_Notify
+# define PR_NotifyAll VBoxNsprPR_NotifyAll
+# define PR_Wait VBoxNsprPR_Wait
+# define PR_NewMonitor VBoxNsprPR_NewMonitor
+# define PR_DestroyMonitor VBoxNsprPR_DestroyMonitor
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef PRUint32 PRIntervalTime;
+
+#define PR_INTERVAL_MIN 1000UL
+#define PR_INTERVAL_MAX 100000UL
+#define PR_INTERVAL_NO_WAIT 0UL
+#define PR_INTERVAL_NO_TIMEOUT 0xffffffffUL
+
+NSPR_API(PRIntervalTime) PR_IntervalNow(void);
+NSPR_API(PRUint32) PR_TicksPerSecond(void);
+NSPR_API(PRIntervalTime) PR_SecondsToInterval(PRUint32 seconds);
+NSPR_API(PRIntervalTime) PR_MillisecondsToInterval(PRUint32 milli);
+NSPR_API(PRIntervalTime) PR_MicrosecondsToInterval(PRUint32 micro);
+NSPR_API(PRUint32) PR_IntervalToSeconds(PRIntervalTime ticks);
+NSPR_API(PRUint32) PR_IntervalToMilliseconds(PRIntervalTime ticks);
+NSPR_API(PRUint32) PR_IntervalToMicroseconds(PRIntervalTime ticks);
+
+typedef struct PRMonitor PRMonitor;
+
+NSPR_API(PRMonitor*) PR_NewMonitor(void);
+NSPR_API(void) PR_DestroyMonitor(PRMonitor *mon);
+NSPR_API(void) PR_EnterMonitor(PRMonitor *mon);
+NSPR_API(PRStatus) PR_ExitMonitor(PRMonitor *mon);
+NSPR_API(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks);
+NSPR_API(PRStatus) PR_Notify(PRMonitor *mon);
+NSPR_API(PRStatus) PR_NotifyAll(PRMonitor *mon);
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PR_CreateThread VBoxNsprPR_CreateThread
+# define PR_JoinThread VBoxNsprPR_JoinThread
+# define PR_Sleep VBoxNsprPR_Sleep
+# define PR_GetCurrentThread VBoxNsprPR_GetCurrentThread
+# define PR_GetThreadState VBoxNsprPR_GetThreadState
+# define PR_SetThreadPrivate VBoxNsprPR_SetThreadPrivate
+# define PR_GetThreadPrivate VBoxNsprPR_GetThreadPrivate
+# define PR_NewThreadPrivateIndex VBoxNsprPR_NewThreadPrivateIndex
+# define PR_GetThreadPriority VBoxNsprPR_GetThreadPriority
+# define PR_SetThreadPriority VBoxNsprPR_SetThreadPriority
+# define PR_Interrupt VBoxNsprPR_Interrupt
+# define PR_ClearInterrupt VBoxNsprPR_ClearInterrupt
+# define PR_BlockInterrupt VBoxNsprPR_BlockInterrupt
+# define PR_UnblockInterrupt VBoxNsprPR_UnblockInterrupt
+# define PR_GetThreadScope VBoxNsprPR_GetThreadScope
+# define PR_GetThreadType VBoxNsprPR_GetThreadType
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef struct PRThread PRThread;
+typedef struct PRThreadStack PRThreadStack;
+
+typedef enum PRThreadType {
+ PR_USER_THREAD,
+ PR_SYSTEM_THREAD
+} PRThreadType;
+
+typedef enum PRThreadScope {
+ PR_LOCAL_THREAD,
+ PR_GLOBAL_THREAD,
+ PR_GLOBAL_BOUND_THREAD
+} PRThreadScope;
+
+typedef enum PRThreadState {
+ PR_JOINABLE_THREAD,
+ PR_UNJOINABLE_THREAD
+} PRThreadState;
+
+typedef enum PRThreadPriority
+{
+ PR_PRIORITY_FIRST = 0, /* just a placeholder */
+ PR_PRIORITY_LOW = 0, /* the lowest possible priority */
+ PR_PRIORITY_NORMAL = 1, /* most common expected priority */
+ PR_PRIORITY_HIGH = 2, /* slightly more aggressive scheduling */
+ PR_PRIORITY_URGENT = 3, /* it does little good to have more than one */
+ PR_PRIORITY_LAST = 3 /* this is just a placeholder */
+} PRThreadPriority;
+
+NSPR_API(PRThread*) PR_CreateThread(PRThreadType type,
+ void (PR_CALLBACK *start)(void *arg),
+ void *arg,
+ PRThreadPriority priority,
+ PRThreadScope scope,
+ PRThreadState state,
+ PRUint32 stackSize);
+NSPR_API(PRStatus) PR_JoinThread(PRThread *thread);
+NSPR_API(PRThread*) PR_GetCurrentThread(void);
+#ifndef NO_NSPR_10_SUPPORT
+#define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */
+#endif /* NO_NSPR_10_SUPPORT */
+NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread);
+NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority);
+
+typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv);
+
+NSPR_API(PRStatus) PR_NewThreadPrivateIndex(
+ PRUintn *newIndex, PRThreadPrivateDTOR destructor);
+NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv);
+NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex);
+NSPR_API(PRStatus) PR_Interrupt(PRThread *thread);
+NSPR_API(void) PR_ClearInterrupt(void);
+NSPR_API(void) PR_BlockInterrupt(void);
+NSPR_API(void) PR_UnblockInterrupt(void);
+NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks);
+NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread);
+NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread);
+NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread);
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PR_DestroyLock VBoxNsprPR_DestroyLock
+# define PR_Lock VBoxNsprPR_Lock
+# define PR_NewLock VBoxNsprPR_NewLock
+# define PR_Unlock VBoxNsprPR_Unlock
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef struct PRLock PRLock;
+
+NSPR_API(PRLock*) PR_NewLock(void);
+NSPR_API(void) PR_DestroyLock(PRLock *lock);
+NSPR_API(void) PR_Lock(PRLock *lock);
+NSPR_API(PRStatus) PR_Unlock(PRLock *lock);
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PR_NewCondVar VBoxNsprPR_NewCondVar
+# define PR_DestroyCondVar VBoxNsprPR_DestroyCondVar
+# define PR_WaitCondVar VBoxNsprPR_WaitCondVar
+# define PR_NotifyCondVar VBoxNsprPR_NotifyCondVar
+# define PR_NotifyAllCondVar VBoxNsprPR_NotifyAllCondVar
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef struct PRCondVar PRCondVar;
+
+NSPR_API(PRCondVar*) PR_NewCondVar(PRLock *lock);
+NSPR_API(void) PR_DestroyCondVar(PRCondVar *cvar);
+NSPR_API(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout);
+NSPR_API(PRStatus) PR_NotifyCondVar(PRCondVar *cvar);
+NSPR_API(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar);
+
+typedef struct PRCListStr PRCList;
+
+struct PRCListStr {
+ PRCList *next;
+ PRCList *prev;
+};
+
+#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP
+# define PL_DestroyEvent VBoxNsplPL_DestroyEvent
+# define PL_HandleEvent VBoxNsplPL_HandleEvent
+# define PL_InitEvent VBoxNsplPL_InitEvent
+# define PL_CreateEventQueue VBoxNsplPL_CreateEventQueue
+# define PL_CreateMonitoredEventQueue VBoxNsplPL_CreateMonitoredEventQueue
+# define PL_CreateNativeEventQueue VBoxNsplPL_CreateNativeEventQueue
+# define PL_DequeueEvent VBoxNsplPL_DequeueEvent
+# define PL_DestroyEventQueue VBoxNsplPL_DestroyEventQueue
+# define PL_EventAvailable VBoxNsplPL_EventAvailable
+# define PL_EventLoop VBoxNsplPL_EventLoop
+# define PL_GetEvent VBoxNsplPL_GetEvent
+# define PL_GetEventOwner VBoxNsplPL_GetEventOwner
+# define PL_GetEventQueueMonitor VBoxNsplPL_GetEventQueueMonitor
+# define PL_GetEventQueueSelectFD VBoxNsplPL_GetEventQueueSelectFD
+# define PL_MapEvents VBoxNsplPL_MapEvents
+# define PL_PostEvent VBoxNsplPL_PostEvent
+# define PL_PostSynchronousEvent VBoxNsplPL_PostSynchronousEvent
+# define PL_ProcessEventsBeforeID VBoxNsplPL_ProcessEventsBeforeID
+# define PL_ProcessPendingEvents VBoxNsplPL_ProcessPendingEvents
+# define PL_RegisterEventIDFunc VBoxNsplPL_RegisterEventIDFunc
+# define PL_RevokeEvents VBoxNsplPL_RevokeEvents
+# define PL_UnregisterEventIDFunc VBoxNsplPL_UnregisterEventIDFunc
+# define PL_WaitForEvent VBoxNsplPL_WaitForEvent
+# define PL_IsQueueNative VBoxNsplPL_IsQueueNative
+# define PL_IsQueueOnCurrentThread VBoxNsplPL_IsQueueOnCurrentThread
+# define PL_FavorPerformanceHint VBoxNsplPL_FavorPerformanceHint
+#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */
+
+typedef struct PLEvent PLEvent;
+typedef struct PLEventQueue PLEventQueue;
+
+PR_EXTERN(PLEventQueue*)
+PL_CreateEventQueue(const char* name, PRThread* handlerThread);
+PR_EXTERN(PLEventQueue *)
+ PL_CreateNativeEventQueue(
+ const char *name,
+ PRThread *handlerThread
+ );
+PR_EXTERN(PLEventQueue *)
+ PL_CreateMonitoredEventQueue(
+ const char *name,
+ PRThread *handlerThread
+ );
+PR_EXTERN(void)
+PL_DestroyEventQueue(PLEventQueue* self);
+PR_EXTERN(PRMonitor*)
+PL_GetEventQueueMonitor(PLEventQueue* self);
+
+#define PL_ENTER_EVENT_QUEUE_MONITOR(queue) \
+ PR_EnterMonitor(PL_GetEventQueueMonitor(queue))
+
+#define PL_EXIT_EVENT_QUEUE_MONITOR(queue) \
+ PR_ExitMonitor(PL_GetEventQueueMonitor(queue))
+
+PR_EXTERN(PRStatus) PL_PostEvent(PLEventQueue* self, PLEvent* event);
+PR_EXTERN(void*) PL_PostSynchronousEvent(PLEventQueue* self, PLEvent* event);
+PR_EXTERN(PLEvent*) PL_GetEvent(PLEventQueue* self);
+PR_EXTERN(PRBool) PL_EventAvailable(PLEventQueue* self);
+
+typedef void (PR_CALLBACK *PLEventFunProc)(PLEvent* event, void* data, PLEventQueue* queue);
+
+PR_EXTERN(void) PL_MapEvents(PLEventQueue* self, PLEventFunProc fun, void* data);
+PR_EXTERN(void) PL_RevokeEvents(PLEventQueue* self, void* owner);
+PR_EXTERN(void) PL_ProcessPendingEvents(PLEventQueue* self);
+PR_EXTERN(PLEvent*) PL_WaitForEvent(PLEventQueue* self);
+PR_EXTERN(void) PL_EventLoop(PLEventQueue* self);
+PR_EXTERN(PRInt32) PL_GetEventQueueSelectFD(PLEventQueue* self);
+PR_EXTERN(PRBool) PL_IsQueueOnCurrentThread( PLEventQueue *queue );
+PR_EXTERN(PRBool) PL_IsQueueNative(PLEventQueue *queue);
+
+typedef void* (PR_CALLBACK *PLHandleEventProc)(PLEvent* self);
+typedef void (PR_CALLBACK *PLDestroyEventProc)(PLEvent* self);
+PR_EXTERN(void)
+PL_InitEvent(PLEvent* self, void* owner,
+ PLHandleEventProc handler,
+ PLDestroyEventProc destructor);
+PR_EXTERN(void*) PL_GetEventOwner(PLEvent* self);
+PR_EXTERN(void) PL_HandleEvent(PLEvent* self);
+PR_EXTERN(void) PL_DestroyEvent(PLEvent* self);
+PR_EXTERN(void) PL_DequeueEvent(PLEvent* self, PLEventQueue* queue);
+PR_EXTERN(void) PL_FavorPerformanceHint(PRBool favorPerformanceOverEventStarvation, PRUint32 starvationDelay);
+
+struct PLEvent {
+ PRCList link;
+ PLHandleEventProc handler;
+ PLDestroyEventProc destructor;
+ void* owner;
+ void* synchronousResult;
+ PRLock* lock;
+ PRCondVar* condVar;
+ PRBool handled;
+#ifdef PL_POST_TIMINGS
+ PRIntervalTime postTime;
+#endif
+#ifdef XP_UNIX
+ unsigned long id;
+#endif /* XP_UNIX */
+ /* other fields follow... */
+};
+
+#if defined(XP_WIN) || defined(XP_OS2)
+
+PR_EXTERN(HWND)
+ PL_GetNativeEventReceiverWindow(
+ PLEventQueue *eqp
+ );
+#endif /* XP_WIN || XP_OS2 */
+
+#ifdef XP_UNIX
+
+PR_EXTERN(PRInt32)
+PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID);
+
+typedef unsigned long (PR_CALLBACK *PLGetEventIDFunc)(void *aClosure);
+
+PR_EXTERN(void)
+PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
+ void *aClosure);
+PR_EXTERN(void) PL_UnregisterEventIDFunc(PLEventQueue *aSelf);
+
+#endif /* XP_UNIX */
+
+/* Standard "it worked" return value */
+#define NS_OK 0
+
+#define NS_ERROR_BASE ((nsresult) 0xC1F30000)
+
+/* Returned when an instance is not initialized */
+#define NS_ERROR_NOT_INITIALIZED (NS_ERROR_BASE + 1)
+
+/* Returned when an instance is already initialized */
+#define NS_ERROR_ALREADY_INITIALIZED (NS_ERROR_BASE + 2)
+
+/* Returned by a not implemented function */
+#define NS_ERROR_NOT_IMPLEMENTED ((nsresult) 0x80004001L)
+
+/* Returned when a given interface is not supported. */
+#define NS_NOINTERFACE ((nsresult) 0x80004002L)
+#define NS_ERROR_NO_INTERFACE NS_NOINTERFACE
+
+#define NS_ERROR_INVALID_POINTER ((nsresult) 0x80004003L)
+#define NS_ERROR_NULL_POINTER NS_ERROR_INVALID_POINTER
+
+/* Returned when a function aborts */
+#define NS_ERROR_ABORT ((nsresult) 0x80004004L)
+
+/* Returned when a function fails */
+#define NS_ERROR_FAILURE ((nsresult) 0x80004005L)
+
+/* Returned when an unexpected error occurs */
+#define NS_ERROR_UNEXPECTED ((nsresult) 0x8000ffffL)
+
+/* Returned when a memory allocation fails */
+#define NS_ERROR_OUT_OF_MEMORY ((nsresult) 0x8007000eL)
+
+/* Returned when an illegal value is passed */
+#define NS_ERROR_ILLEGAL_VALUE ((nsresult) 0x80070057L)
+#define NS_ERROR_INVALID_ARG NS_ERROR_ILLEGAL_VALUE
+
+/* Returned when a class doesn't allow aggregation */
+#define NS_ERROR_NO_AGGREGATION ((nsresult) 0x80040110L)
+
+/* Returned when an operation can't complete due to an unavailable resource */
+#define NS_ERROR_NOT_AVAILABLE ((nsresult) 0x80040111L)
+
+/* Returned when a class is not registered */
+#define NS_ERROR_FACTORY_NOT_REGISTERED ((nsresult) 0x80040154L)
+
+/* Returned when a class cannot be registered, but may be tried again later */
+#define NS_ERROR_FACTORY_REGISTER_AGAIN ((nsresult) 0x80040155L)
+
+/* Returned when a dynamically loaded factory couldn't be found */
+#define NS_ERROR_FACTORY_NOT_LOADED ((nsresult) 0x800401f8L)
+
+/* Returned when a factory doesn't support signatures */
+#define NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT \
+ (NS_ERROR_BASE + 0x101)
+
+/* Returned when a factory already is registered */
+#define NS_ERROR_FACTORY_EXISTS (NS_ERROR_BASE + 0x100)
+
+
+/**
+ * An "interface id" which can be used to uniquely identify a given
+ * interface.
+ * A "unique identifier". This is modeled after OSF DCE UUIDs.
+ */
+
+struct nsID {
+ PRUint32 m0;
+ PRUint16 m1;
+ PRUint16 m2;
+ PRUint8 m3[8];
+};
+
+typedef struct nsID nsID;
+typedef nsID nsIID;
+
+struct nsISupports; /* forward declaration */
+struct nsIStackFrame; /* forward declaration */
+struct nsIException; /* forward declaration */
+typedef struct nsISupports nsISupports; /* forward declaration */
+typedef struct nsIStackFrame nsIStackFrame; /* forward declaration */
+typedef struct nsIException nsIException; /* forward declaration */
+
+/**
+ * IID for the nsISupports interface
+ * {00000000-0000-0000-c000-000000000046}
+ *
+ * To maintain binary compatibility with COM's IUnknown, we define the IID
+ * of nsISupports to be the same as that of COM's IUnknown.
+ */
+#define NS_ISUPPORTS_IID \
+ { 0x00000000, 0x0000, 0x0000, \
+ {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }
+
+/**
+ * Reference count values
+ *
+ * This is the return type for AddRef() and Release() in nsISupports.
+ * IUnknown of COM returns an unsigned long from equivalent functions.
+ * The following ifdef exists to maintain binary compatibility with
+ * IUnknown.
+ */
+
+/**
+ * Basic component object model interface. Objects which implement
+ * this interface support runtime interface discovery (QueryInterface)
+ * and a reference counted memory model (AddRef/Release). This is
+ * modelled after the win32 IUnknown API.
+ */
+struct nsISupports_vtbl {
+
+ /**
+ * @name Methods
+ */
+
+ /**
+ * A run time mechanism for interface discovery.
+ * @param aIID [in] A requested interface IID
+ * @param aInstancePtr [out] A pointer to an interface pointer to
+ * receive the result.
+ * @return NS_OK if the interface is supported by the associated
+ * instance, NS_NOINTERFACE if it is not.
+ * NS_ERROR_INVALID_POINTER if aInstancePtr is NULL.
+ */
+ nsresult (*QueryInterface)(nsISupports *pThis, const nsID *iid, void **resultp);
+ /**
+ * Increases the reference count for this interface.
+ * The associated instance will not be deleted unless
+ * the reference count is returned to zero.
+ *
+ * @return The resulting reference count.
+ */
+ nsresult (*AddRef)(nsISupports *pThis);
+
+ /**
+ * Decreases the reference count for this interface.
+ * Generally, if the reference count returns to zero,
+ * the associated instance is deleted.
+ *
+ * @return The resulting reference count.
+ */
+ nsresult (*Release)(nsISupports *pThis);
+
+};
+
+struct nsISupports {
+ struct nsISupports_vtbl *vtbl;
+};
+
+/* starting interface: nsIException */
+#define NS_IEXCEPTION_IID_STR "f3a8d3b4-c424-4edc-8bf6-8974c983ba78"
+
+#define NS_IEXCEPTION_IID \
+ {0xf3a8d3b4, 0xc424, 0x4edc, \
+ { 0x8b, 0xf6, 0x89, 0x74, 0xc9, 0x83, 0xba, 0x78 }}
+
+struct nsIException_vtbl {
+
+ /* Methods from the Class nsISupports */
+ struct nsISupports_vtbl nsisupports;
+
+ /* readonly attribute string message; */
+ nsresult (*GetMessage)(nsIException *pThis, PRUnichar * *aMessage);
+
+ /* readonly attribute nsresult (*result; */
+ nsresult (*GetResult)(nsIException *pThis, nsresult *aResult);
+
+ /* readonly attribute string name; */
+ nsresult (*GetName)(nsIException *pThis, PRUnichar * *aName);
+
+ /* readonly attribute string filename; */
+ nsresult (*GetFilename)(nsIException *pThis, PRUnichar * *aFilename);
+
+ /* readonly attribute PRUint32 lineNumber; */
+ nsresult (*GetLineNumber)(nsIException *pThis, PRUint32 *aLineNumber);
+
+ /* readonly attribute PRUint32 columnNumber; */
+ nsresult (*GetColumnNumber)(nsIException *pThis, PRUint32 *aColumnNumber);
+
+ /* readonly attribute nsIStackFrame location; */
+ nsresult (*GetLocation)(nsIException *pThis, nsIStackFrame * *aLocation);
+
+ /* readonly attribute nsIException inner; */
+ nsresult (*GetInner)(nsIException *pThis, nsIException * *aInner);
+
+ /* readonly attribute nsISupports data; */
+ nsresult (*GetData)(nsIException *pThis, nsISupports * *aData);
+
+ /* string toString (); */
+ nsresult (*ToString)(nsIException *pThis, PRUnichar **_retval);
+};
+
+struct nsIException {
+ struct nsIException_vtbl *vtbl;
+};
+
+/* starting interface: nsIStackFrame */
+#define NS_ISTACKFRAME_IID_STR "91d82105-7c62-4f8b-9779-154277c0ee90"
+
+#define NS_ISTACKFRAME_IID \
+ {0x91d82105, 0x7c62, 0x4f8b, \
+ { 0x97, 0x79, 0x15, 0x42, 0x77, 0xc0, 0xee, 0x90 }}
+
+struct nsIStackFrame_vtbl {
+
+ /* Methods from the Class nsISupports */
+ struct nsISupports_vtbl nsisupports;
+
+ /* readonly attribute PRUint32 language; */
+ nsresult (*GetLanguage)(nsIStackFrame *pThis, PRUint32 *aLanguage);
+
+ /* readonly attribute string languageName; */
+ nsresult (*GetLanguageName)(nsIStackFrame *pThis, PRUnichar * *aLanguageName);
+
+ /* readonly attribute string filename; */
+ nsresult (*GetFilename)(nsIStackFrame *pThis, PRUnichar * *aFilename);
+
+ /* readonly attribute string name; */
+ nsresult (*GetName)(nsIStackFrame *pThis, PRUnichar * *aName);
+
+ /* readonly attribute PRInt32 lineNumber; */
+ nsresult (*GetLineNumber)(nsIStackFrame *pThis, PRInt32 *aLineNumber);
+
+ /* readonly attribute string sourceLine; */
+ nsresult (*GetSourceLine)(nsIStackFrame *pThis, PRUnichar * *aSourceLine);
+
+ /* readonly attribute nsIStackFrame caller; */
+ nsresult (*GetCaller)(nsIStackFrame *pThis, nsIStackFrame * *aCaller);
+
+ /* string toString (); */
+ nsresult (*ToString)(nsIStackFrame *pThis, PRUnichar **_retval);
+};
+
+struct nsIStackFrame {
+ struct nsIStackFrame_vtbl *vtbl;
+};
+
+/* starting interface: nsIEventTarget */
+#define NS_IEVENTTARGET_IID_STR "ea99ad5b-cc67-4efb-97c9-2ef620a59f2a"
+
+#define NS_IEVENTTARGET_IID \
+ {0xea99ad5b, 0xcc67, 0x4efb, \
+ { 0x97, 0xc9, 0x2e, 0xf6, 0x20, 0xa5, 0x9f, 0x2a }}
+
+struct nsIEventTarget;
+typedef struct nsIEventTarget nsIEventTarget;
+
+struct nsIEventTarget_vtbl {
+
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*PostEvent)(nsIEventTarget *pThis, PLEvent * aEvent);
+
+ nsresult (*IsOnCurrentThread)(nsIEventTarget *pThis, PRBool *_retval);
+
+};
+
+struct nsIEventTarget {
+ struct nsIEventTarget_vtbl *vtbl;
+};
+
+/* starting interface: nsIEventQueue */
+#define NS_IEVENTQUEUE_IID_STR "176afb41-00a4-11d3-9f2a-00400553eef0"
+
+#define NS_IEVENTQUEUE_IID \
+ {0x176afb41, 0x00a4, 0x11d3, \
+ { 0x9f, 0x2a, 0x00, 0x40, 0x05, 0x53, 0xee, 0xf0 }}
+
+struct nsIEventQueue;
+typedef struct nsIEventQueue nsIEventQueue;
+
+struct nsIEventQueue_vtbl {
+
+ struct nsIEventTarget_vtbl nsieventtarget;
+
+ nsresult (*InitEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * owner, PLHandleEventProc handler, PLDestroyEventProc destructor);
+
+ nsresult (*PostSynchronousEvent)(nsIEventQueue *pThis, PLEvent * aEvent, void * *aResult);
+
+ nsresult (*PendingEvents)(nsIEventQueue *pThis, PRBool *_retval);
+
+ nsresult (*ProcessPendingEvents)(nsIEventQueue *pThis);
+
+ nsresult (*EventLoop)(nsIEventQueue *pThis);
+
+ nsresult (*EventAvailable)(nsIEventQueue *pThis, PRBool *aResult);
+
+ nsresult (*GetEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
+
+ nsresult (*HandleEvent)(nsIEventQueue *pThis, PLEvent * aEvent);
+
+ nsresult (*WaitForEvent)(nsIEventQueue *pThis, PLEvent * *_retval);
+
+ PRInt32 (*GetEventQueueSelectFD)(nsIEventQueue *pThis);
+
+ nsresult (*Init)(nsIEventQueue *pThis, PRBool aNative);
+
+ nsresult (*InitFromPRThread)(nsIEventQueue *pThis, PRThread * thread, PRBool aNative);
+
+ nsresult (*InitFromPLQueue)(nsIEventQueue *pThis, PLEventQueue * aQueue);
+
+ nsresult (*EnterMonitor)(nsIEventQueue *pThis);
+
+ nsresult (*ExitMonitor)(nsIEventQueue *pThis);
+
+ nsresult (*RevokeEvents)(nsIEventQueue *pThis, void * owner);
+
+ nsresult (*GetPLEventQueue)(nsIEventQueue *pThis, PLEventQueue * *_retval);
+
+ nsresult (*IsQueueNative)(nsIEventQueue *pThis, PRBool *_retval);
+
+ nsresult (*StopAcceptingEvents)(nsIEventQueue *pThis);
+
+};
+
+struct nsIEventQueue {
+ struct nsIEventQueue_vtbl *vtbl;
+};
+
+
+#define VBOX_E_OBJECT_NOT_FOUND 0x80BB0001
+#define VBOX_E_INVALID_VM_STATE 0x80BB0002
+#define VBOX_E_VM_ERROR 0x80BB0003
+#define VBOX_E_FILE_ERROR 0x80BB0004
+#define VBOX_E_IPRT_ERROR 0x80BB0005
+#define VBOX_E_PDM_ERROR 0x80BB0006
+#define VBOX_E_INVALID_OBJECT_STATE 0x80BB0007
+#define VBOX_E_HOST_ERROR 0x80BB0008
+#define VBOX_E_NOT_SUPPORTED 0x80BB0009
+#define VBOX_E_XML_ERROR 0x80BB000A
+#define VBOX_E_INVALID_SESSION_STATE 0x80BB000B
+#define VBOX_E_OBJECT_IN_USE 0x80BB000C
+
+
+struct IVirtualBoxErrorInfo;
+struct IDHCPServer;
+struct IVirtualBox;
+struct IVFSExplorer;
+struct IAppliance;
+struct IVirtualSystemDescription;
+struct IInternalMachineControl;
+struct IBIOSSettings;
+struct IPciAddress;
+struct IPciDeviceAttachment;
+struct IMachine;
+struct IVRDEServerInfo;
+struct IConsole;
+struct IHostNetworkInterface;
+struct IHost;
+struct ISystemProperties;
+struct IGuestOSType;
+struct IAdditionsFacility;
+struct IGuestDirEntry;
+struct IGuest;
+struct IProgress;
+struct ISnapshot;
+struct IMediumAttachment;
+struct IMedium;
+struct IMediumFormat;
+struct IKeyboard;
+struct IMouse;
+struct IFramebuffer;
+struct IFramebufferOverlay;
+struct IDisplay;
+struct INetworkAdapter;
+struct ISerialPort;
+struct IParallelPort;
+struct IMachineDebugger;
+struct IUSBController;
+struct IUSBDevice;
+struct IUSBDeviceFilter;
+struct IHostUSBDevice;
+struct IHostUSBDeviceFilter;
+struct IAudioAdapter;
+struct IVRDEServer;
+struct ISharedFolder;
+struct IInternalSessionControl;
+struct ISession;
+struct IStorageController;
+struct IManagedObjectRef;
+struct IWebsessionManager;
+struct IPerformanceMetric;
+struct IPerformanceCollector;
+struct INATEngine;
+struct IExtPackPlugIn;
+struct IExtPackBase;
+struct IExtPack;
+struct IExtPackFile;
+struct IExtPackManager;
+struct IBandwidthGroup;
+struct IBandwidthControl;
+struct IVirtualBoxClient;
+struct IEventSource;
+struct IEventListener;
+struct IEvent;
+struct IReusableEvent;
+struct IMachineEvent;
+struct IMachineStateChangedEvent;
+struct IMachineDataChangedEvent;
+struct IMediumRegisteredEvent;
+struct IMachineRegisteredEvent;
+struct ISessionStateChangedEvent;
+struct IGuestPropertyChangedEvent;
+struct ISnapshotEvent;
+struct ISnapshotTakenEvent;
+struct ISnapshotDeletedEvent;
+struct ISnapshotChangedEvent;
+struct IMousePointerShapeChangedEvent;
+struct IMouseCapabilityChangedEvent;
+struct IKeyboardLedsChangedEvent;
+struct IStateChangedEvent;
+struct IAdditionsStateChangedEvent;
+struct INetworkAdapterChangedEvent;
+struct ISerialPortChangedEvent;
+struct IParallelPortChangedEvent;
+struct IStorageControllerChangedEvent;
+struct IMediumChangedEvent;
+struct ICPUChangedEvent;
+struct ICPUExecutionCapChangedEvent;
+struct IGuestKeyboardEvent;
+struct IGuestMouseEvent;
+struct IVRDEServerChangedEvent;
+struct IVRDEServerInfoChangedEvent;
+struct IUSBControllerChangedEvent;
+struct IUSBDeviceStateChangedEvent;
+struct ISharedFolderChangedEvent;
+struct IRuntimeErrorEvent;
+struct IEventSourceChangedEvent;
+struct IExtraDataChangedEvent;
+struct IVetoEvent;
+struct IExtraDataCanChangeEvent;
+struct ICanShowWindowEvent;
+struct IShowWindowEvent;
+struct INATRedirectEvent;
+struct IHostPciDevicePlugEvent;
+struct IVBoxSVCAvailabilityChangedEvent;
+struct IBandwidthGroupChangedEvent;
+struct IGuestMonitorChangedEvent;
+struct IStorageDeviceChangedEvent;
+
+typedef struct IVirtualBoxErrorInfo IVirtualBoxErrorInfo;
+typedef struct IDHCPServer IDHCPServer;
+typedef struct IVirtualBox IVirtualBox;
+typedef struct IVFSExplorer IVFSExplorer;
+typedef struct IAppliance IAppliance;
+typedef struct IVirtualSystemDescription IVirtualSystemDescription;
+typedef struct IInternalMachineControl IInternalMachineControl;
+typedef struct IBIOSSettings IBIOSSettings;
+typedef struct IPciAddress IPciAddress;
+typedef struct IPciDeviceAttachment IPciDeviceAttachment;
+typedef struct IMachine IMachine;
+typedef struct IVRDEServerInfo IVRDEServerInfo;
+typedef struct IConsole IConsole;
+typedef struct IHostNetworkInterface IHostNetworkInterface;
+typedef struct IHost IHost;
+typedef struct ISystemProperties ISystemProperties;
+typedef struct IGuestOSType IGuestOSType;
+typedef struct IAdditionsFacility IAdditionsFacility;
+typedef struct IGuestDirEntry IGuestDirEntry;
+typedef struct IGuest IGuest;
+typedef struct IProgress IProgress;
+typedef struct ISnapshot ISnapshot;
+typedef struct IMediumAttachment IMediumAttachment;
+typedef struct IMedium IMedium;
+typedef struct IMediumFormat IMediumFormat;
+typedef struct IKeyboard IKeyboard;
+typedef struct IMouse IMouse;
+typedef struct IFramebuffer IFramebuffer;
+typedef struct IFramebufferOverlay IFramebufferOverlay;
+typedef struct IDisplay IDisplay;
+typedef struct INetworkAdapter INetworkAdapter;
+typedef struct ISerialPort ISerialPort;
+typedef struct IParallelPort IParallelPort;
+typedef struct IMachineDebugger IMachineDebugger;
+typedef struct IUSBController IUSBController;
+typedef struct IUSBDevice IUSBDevice;
+typedef struct IUSBDeviceFilter IUSBDeviceFilter;
+typedef struct IHostUSBDevice IHostUSBDevice;
+typedef struct IHostUSBDeviceFilter IHostUSBDeviceFilter;
+typedef struct IAudioAdapter IAudioAdapter;
+typedef struct IVRDEServer IVRDEServer;
+typedef struct ISharedFolder ISharedFolder;
+typedef struct IInternalSessionControl IInternalSessionControl;
+typedef struct ISession ISession;
+typedef struct IStorageController IStorageController;
+typedef struct IManagedObjectRef IManagedObjectRef;
+typedef struct IWebsessionManager IWebsessionManager;
+typedef struct IPerformanceMetric IPerformanceMetric;
+typedef struct IPerformanceCollector IPerformanceCollector;
+typedef struct INATEngine INATEngine;
+typedef struct IExtPackPlugIn IExtPackPlugIn;
+typedef struct IExtPackBase IExtPackBase;
+typedef struct IExtPack IExtPack;
+typedef struct IExtPackFile IExtPackFile;
+typedef struct IExtPackManager IExtPackManager;
+typedef struct IBandwidthGroup IBandwidthGroup;
+typedef struct IBandwidthControl IBandwidthControl;
+typedef struct IVirtualBoxClient IVirtualBoxClient;
+typedef struct IEventSource IEventSource;
+typedef struct IEventListener IEventListener;
+typedef struct IEvent IEvent;
+typedef struct IReusableEvent IReusableEvent;
+typedef struct IMachineEvent IMachineEvent;
+typedef struct IMachineStateChangedEvent IMachineStateChangedEvent;
+typedef struct IMachineDataChangedEvent IMachineDataChangedEvent;
+typedef struct IMediumRegisteredEvent IMediumRegisteredEvent;
+typedef struct IMachineRegisteredEvent IMachineRegisteredEvent;
+typedef struct ISessionStateChangedEvent ISessionStateChangedEvent;
+typedef struct IGuestPropertyChangedEvent IGuestPropertyChangedEvent;
+typedef struct ISnapshotEvent ISnapshotEvent;
+typedef struct ISnapshotTakenEvent ISnapshotTakenEvent;
+typedef struct ISnapshotDeletedEvent ISnapshotDeletedEvent;
+typedef struct ISnapshotChangedEvent ISnapshotChangedEvent;
+typedef struct IMousePointerShapeChangedEvent IMousePointerShapeChangedEvent;
+typedef struct IMouseCapabilityChangedEvent IMouseCapabilityChangedEvent;
+typedef struct IKeyboardLedsChangedEvent IKeyboardLedsChangedEvent;
+typedef struct IStateChangedEvent IStateChangedEvent;
+typedef struct IAdditionsStateChangedEvent IAdditionsStateChangedEvent;
+typedef struct INetworkAdapterChangedEvent INetworkAdapterChangedEvent;
+typedef struct ISerialPortChangedEvent ISerialPortChangedEvent;
+typedef struct IParallelPortChangedEvent IParallelPortChangedEvent;
+typedef struct IStorageControllerChangedEvent IStorageControllerChangedEvent;
+typedef struct IMediumChangedEvent IMediumChangedEvent;
+typedef struct ICPUChangedEvent ICPUChangedEvent;
+typedef struct ICPUExecutionCapChangedEvent ICPUExecutionCapChangedEvent;
+typedef struct IGuestKeyboardEvent IGuestKeyboardEvent;
+typedef struct IGuestMouseEvent IGuestMouseEvent;
+typedef struct IVRDEServerChangedEvent IVRDEServerChangedEvent;
+typedef struct IVRDEServerInfoChangedEvent IVRDEServerInfoChangedEvent;
+typedef struct IUSBControllerChangedEvent IUSBControllerChangedEvent;
+typedef struct IUSBDeviceStateChangedEvent IUSBDeviceStateChangedEvent;
+typedef struct ISharedFolderChangedEvent ISharedFolderChangedEvent;
+typedef struct IRuntimeErrorEvent IRuntimeErrorEvent;
+typedef struct IEventSourceChangedEvent IEventSourceChangedEvent;
+typedef struct IExtraDataChangedEvent IExtraDataChangedEvent;
+typedef struct IVetoEvent IVetoEvent;
+typedef struct IExtraDataCanChangeEvent IExtraDataCanChangeEvent;
+typedef struct ICanShowWindowEvent ICanShowWindowEvent;
+typedef struct IShowWindowEvent IShowWindowEvent;
+typedef struct INATRedirectEvent INATRedirectEvent;
+typedef struct IHostPciDevicePlugEvent IHostPciDevicePlugEvent;
+typedef struct IVBoxSVCAvailabilityChangedEvent IVBoxSVCAvailabilityChangedEvent;
+typedef struct IBandwidthGroupChangedEvent IBandwidthGroupChangedEvent;
+typedef struct IGuestMonitorChangedEvent IGuestMonitorChangedEvent;
+typedef struct IStorageDeviceChangedEvent IStorageDeviceChangedEvent;
+
+/* Start of enum SettingsVersion Declaration */
+#define SETTINGSVERSION_IID_STR "52bd6f5f-1adb-4493-975d-581a9c4b803f"
+#define SETTINGSVERSION_IID { \
+ 0x52bd6f5f, 0x1adb, 0x4493, \
+ { 0x97, 0x5d, 0x58, 0x1a, 0x9c, 0x4b, 0x80, 0x3f } \
+}
+enum SettingsVersion
+{
+ SettingsVersion_Null = 0,
+ SettingsVersion_v1_0 = 1,
+ SettingsVersion_v1_1 = 2,
+ SettingsVersion_v1_2 = 3,
+ SettingsVersion_v1_3pre = 4,
+ SettingsVersion_v1_3 = 5,
+ SettingsVersion_v1_4 = 6,
+ SettingsVersion_v1_5 = 7,
+ SettingsVersion_v1_6 = 8,
+ SettingsVersion_v1_7 = 9,
+ SettingsVersion_v1_8 = 10,
+ SettingsVersion_v1_9 = 11,
+ SettingsVersion_v1_10 = 12,
+ SettingsVersion_v1_11 = 13,
+ SettingsVersion_v1_12 = 14,
+ SettingsVersion_Future = 99999
+};
+/* End of enum SettingsVersion Declaration */
+
+
+/* Start of enum AccessMode Declaration */
+#define ACCESSMODE_IID_STR "1da0007c-ddf7-4be8-bcac-d84a1558785f"
+#define ACCESSMODE_IID { \
+ 0x1da0007c, 0xddf7, 0x4be8, \
+ { 0xbc, 0xac, 0xd8, 0x4a, 0x15, 0x58, 0x78, 0x5f } \
+}
+enum AccessMode
+{
+ AccessMode_ReadOnly = 1,
+ AccessMode_ReadWrite = 2
+};
+/* End of enum AccessMode Declaration */
+
+
+/* Start of enum MachineState Declaration */
+#define MACHINESTATE_IID_STR "ec6c6a9e-113d-4ff4-b44f-0b69f21c97fe"
+#define MACHINESTATE_IID { \
+ 0xec6c6a9e, 0x113d, 0x4ff4, \
+ { 0xb4, 0x4f, 0x0b, 0x69, 0xf2, 0x1c, 0x97, 0xfe } \
+}
+enum MachineState
+{
+ MachineState_Null = 0,
+ MachineState_PoweredOff = 1,
+ MachineState_Saved = 2,
+ MachineState_Teleported = 3,
+ MachineState_Aborted = 4,
+ MachineState_Running = 5,
+ MachineState_Paused = 6,
+ MachineState_Stuck = 7,
+ MachineState_Teleporting = 8,
+ MachineState_LiveSnapshotting = 9,
+ MachineState_Starting = 10,
+ MachineState_Stopping = 11,
+ MachineState_Saving = 12,
+ MachineState_Restoring = 13,
+ MachineState_TeleportingPausedVM = 14,
+ MachineState_TeleportingIn = 15,
+ MachineState_FaultTolerantSyncing = 16,
+ MachineState_DeletingSnapshotOnline = 17,
+ MachineState_DeletingSnapshotPaused = 18,
+ MachineState_RestoringSnapshot = 19,
+ MachineState_DeletingSnapshot = 20,
+ MachineState_SettingUp = 21,
+ MachineState_FirstOnline = 5,
+ MachineState_LastOnline = 18,
+ MachineState_FirstTransient = 8,
+ MachineState_LastTransient = 21
+};
+/* End of enum MachineState Declaration */
+
+
+/* Start of enum SessionState Declaration */
+#define SESSIONSTATE_IID_STR "cf2700c0-ea4b-47ae-9725-7810114b94d8"
+#define SESSIONSTATE_IID { \
+ 0xcf2700c0, 0xea4b, 0x47ae, \
+ { 0x97, 0x25, 0x78, 0x10, 0x11, 0x4b, 0x94, 0xd8 } \
+}
+enum SessionState
+{
+ SessionState_Null = 0,
+ SessionState_Unlocked = 1,
+ SessionState_Locked = 2,
+ SessionState_Spawning = 3,
+ SessionState_Unlocking = 4
+};
+/* End of enum SessionState Declaration */
+
+
+/* Start of enum CPUPropertyType Declaration */
+#define CPUPROPERTYTYPE_IID_STR "24d356a6-2f45-4abd-b977-1cbe9c4701f5"
+#define CPUPROPERTYTYPE_IID { \
+ 0x24d356a6, 0x2f45, 0x4abd, \
+ { 0xb9, 0x77, 0x1c, 0xbe, 0x9c, 0x47, 0x01, 0xf5 } \
+}
+enum CPUPropertyType
+{
+ CPUPropertyType_Null = 0,
+ CPUPropertyType_PAE = 1,
+ CPUPropertyType_Synthetic = 2
+};
+/* End of enum CPUPropertyType Declaration */
+
+
+/* Start of enum HWVirtExPropertyType Declaration */
+#define HWVIRTEXPROPERTYTYPE_IID_STR "ce81dfdd-d2b8-4a90-bbea-40ee8b7ffcee"
+#define HWVIRTEXPROPERTYTYPE_IID { \
+ 0xce81dfdd, 0xd2b8, 0x4a90, \
+ { 0xbb, 0xea, 0x40, 0xee, 0x8b, 0x7f, 0xfc, 0xee } \
+}
+enum HWVirtExPropertyType
+{
+ HWVirtExPropertyType_Null = 0,
+ HWVirtExPropertyType_Enabled = 1,
+ HWVirtExPropertyType_Exclusive = 2,
+ HWVirtExPropertyType_VPID = 3,
+ HWVirtExPropertyType_NestedPaging = 4,
+ HWVirtExPropertyType_LargePages = 5,
+ HWVirtExPropertyType_Force = 6
+};
+/* End of enum HWVirtExPropertyType Declaration */
+
+
+/* Start of enum FaultToleranceState Declaration */
+#define FAULTTOLERANCESTATE_IID_STR "5124f7ec-6b67-493c-9dee-ee45a44114e1"
+#define FAULTTOLERANCESTATE_IID { \
+ 0x5124f7ec, 0x6b67, 0x493c, \
+ { 0x9d, 0xee, 0xee, 0x45, 0xa4, 0x41, 0x14, 0xe1 } \
+}
+enum FaultToleranceState
+{
+ FaultToleranceState_Inactive = 1,
+ FaultToleranceState_Master = 2,
+ FaultToleranceState_Standby = 3
+};
+/* End of enum FaultToleranceState Declaration */
+
+
+/* Start of enum LockType Declaration */
+#define LOCKTYPE_IID_STR "138b53f8-db4b-47c5-b32b-4ef52f769413"
+#define LOCKTYPE_IID { \
+ 0x138b53f8, 0xdb4b, 0x47c5, \
+ { 0xb3, 0x2b, 0x4e, 0xf5, 0x2f, 0x76, 0x94, 0x13 } \
+}
+enum LockType
+{
+ LockType_Write = 2,
+ LockType_Shared = 1
+};
+/* End of enum LockType Declaration */
+
+
+/* Start of enum SessionType Declaration */
+#define SESSIONTYPE_IID_STR "A13C02CB-0C2C-421E-8317-AC0E8AAA153A"
+#define SESSIONTYPE_IID { \
+ 0xA13C02CB, 0x0C2C, 0x421E, \
+ { 0x83, 0x17, 0xAC, 0x0E, 0x8A, 0xAA, 0x15, 0x3A } \
+}
+enum SessionType
+{
+ SessionType_Null = 0,
+ SessionType_WriteLock = 1,
+ SessionType_Remote = 2,
+ SessionType_Shared = 3
+};
+/* End of enum SessionType Declaration */
+
+
+/* Start of enum DeviceType Declaration */
+#define DEVICETYPE_IID_STR "6d9420f7-0b56-4636-99f9-7346f1b01e57"
+#define DEVICETYPE_IID { \
+ 0x6d9420f7, 0x0b56, 0x4636, \
+ { 0x99, 0xf9, 0x73, 0x46, 0xf1, 0xb0, 0x1e, 0x57 } \
+}
+enum DeviceType
+{
+ DeviceType_Null = 0,
+ DeviceType_Floppy = 1,
+ DeviceType_DVD = 2,
+ DeviceType_HardDisk = 3,
+ DeviceType_Network = 4,
+ DeviceType_USB = 5,
+ DeviceType_SharedFolder = 6
+};
+/* End of enum DeviceType Declaration */
+
+
+/* Start of enum DeviceActivity Declaration */
+#define DEVICEACTIVITY_IID_STR "6FC8AEAA-130A-4eb5-8954-3F921422D707"
+#define DEVICEACTIVITY_IID { \
+ 0x6FC8AEAA, 0x130A, 0x4eb5, \
+ { 0x89, 0x54, 0x3F, 0x92, 0x14, 0x22, 0xD7, 0x07 } \
+}
+enum DeviceActivity
+{
+ DeviceActivity_Null = 0,
+ DeviceActivity_Idle = 1,
+ DeviceActivity_Reading = 2,
+ DeviceActivity_Writing = 3
+};
+/* End of enum DeviceActivity Declaration */
+
+
+/* Start of enum ClipboardMode Declaration */
+#define CLIPBOARDMODE_IID_STR "33364716-4008-4701-8f14-be0fa3d62950"
+#define CLIPBOARDMODE_IID { \
+ 0x33364716, 0x4008, 0x4701, \
+ { 0x8f, 0x14, 0xbe, 0x0f, 0xa3, 0xd6, 0x29, 0x50 } \
+}
+enum ClipboardMode
+{
+ ClipboardMode_Disabled = 0,
+ ClipboardMode_HostToGuest = 1,
+ ClipboardMode_GuestToHost = 2,
+ ClipboardMode_Bidirectional = 3
+};
+/* End of enum ClipboardMode Declaration */
+
+
+/* Start of enum Scope Declaration */
+#define SCOPE_IID_STR "7c91096e-499e-4eca-9f9b-9001438d7855"
+#define SCOPE_IID { \
+ 0x7c91096e, 0x499e, 0x4eca, \
+ { 0x9f, 0x9b, 0x90, 0x01, 0x43, 0x8d, 0x78, 0x55 } \
+}
+enum Scope
+{
+ Scope_Global = 0,
+ Scope_Machine = 1,
+ Scope_Session = 2
+};
+/* End of enum Scope Declaration */
+
+
+/* Start of enum BIOSBootMenuMode Declaration */
+#define BIOSBOOTMENUMODE_IID_STR "ae4fb9f7-29d2-45b4-b2c7-d579603135d5"
+#define BIOSBOOTMENUMODE_IID { \
+ 0xae4fb9f7, 0x29d2, 0x45b4, \
+ { 0xb2, 0xc7, 0xd5, 0x79, 0x60, 0x31, 0x35, 0xd5 } \
+}
+enum BIOSBootMenuMode
+{
+ BIOSBootMenuMode_Disabled = 0,
+ BIOSBootMenuMode_MenuOnly = 1,
+ BIOSBootMenuMode_MessageAndMenu = 2
+};
+/* End of enum BIOSBootMenuMode Declaration */
+
+
+/* Start of enum ProcessorFeature Declaration */
+#define PROCESSORFEATURE_IID_STR "64c38e6b-8bcf-45ad-ac03-9b406287c5bf"
+#define PROCESSORFEATURE_IID { \
+ 0x64c38e6b, 0x8bcf, 0x45ad, \
+ { 0xac, 0x03, 0x9b, 0x40, 0x62, 0x87, 0xc5, 0xbf } \
+}
+enum ProcessorFeature
+{
+ ProcessorFeature_HWVirtEx = 0,
+ ProcessorFeature_PAE = 1,
+ ProcessorFeature_LongMode = 2,
+ ProcessorFeature_NestedPaging = 3
+};
+/* End of enum ProcessorFeature Declaration */
+
+
+/* Start of enum FirmwareType Declaration */
+#define FIRMWARETYPE_IID_STR "b903f264-c230-483e-ac74-2b37ce60d371"
+#define FIRMWARETYPE_IID { \
+ 0xb903f264, 0xc230, 0x483e, \
+ { 0xac, 0x74, 0x2b, 0x37, 0xce, 0x60, 0xd3, 0x71 } \
+}
+enum FirmwareType
+{
+ FirmwareType_BIOS = 1,
+ FirmwareType_EFI = 2,
+ FirmwareType_EFI32 = 3,
+ FirmwareType_EFI64 = 4,
+ FirmwareType_EFIDUAL = 5
+};
+/* End of enum FirmwareType Declaration */
+
+
+/* Start of enum PointingHidType Declaration */
+#define POINTINGHIDTYPE_IID_STR "0d3c17a2-821a-4b2e-ae41-890c6c60aa97"
+#define POINTINGHIDTYPE_IID { \
+ 0x0d3c17a2, 0x821a, 0x4b2e, \
+ { 0xae, 0x41, 0x89, 0x0c, 0x6c, 0x60, 0xaa, 0x97 } \
+}
+enum PointingHidType
+{
+ PointingHidType_None = 1,
+ PointingHidType_PS2Mouse = 2,
+ PointingHidType_USBMouse = 3,
+ PointingHidType_USBTablet = 4,
+ PointingHidType_ComboMouse = 5
+};
+/* End of enum PointingHidType Declaration */
+
+
+/* Start of enum KeyboardHidType Declaration */
+#define KEYBOARDHIDTYPE_IID_STR "5a5b0996-3a3e-44bb-9019-56979812cbcc"
+#define KEYBOARDHIDTYPE_IID { \
+ 0x5a5b0996, 0x3a3e, 0x44bb, \
+ { 0x90, 0x19, 0x56, 0x97, 0x98, 0x12, 0xcb, 0xcc } \
+}
+enum KeyboardHidType
+{
+ KeyboardHidType_None = 1,
+ KeyboardHidType_PS2Keyboard = 2,
+ KeyboardHidType_USBKeyboard = 3,
+ KeyboardHidType_ComboKeyboard = 4
+};
+/* End of enum KeyboardHidType Declaration */
+
+
+/* Start of enum VFSType Declaration */
+#define VFSTYPE_IID_STR "813999ba-b949-48a8-9230-aadc6285e2f2"
+#define VFSTYPE_IID { \
+ 0x813999ba, 0xb949, 0x48a8, \
+ { 0x92, 0x30, 0xaa, 0xdc, 0x62, 0x85, 0xe2, 0xf2 } \
+}
+enum VFSType
+{
+ VFSType_File = 1,
+ VFSType_Cloud = 2,
+ VFSType_S3 = 3,
+ VFSType_WebDav = 4
+};
+/* End of enum VFSType Declaration */
+
+
+/* Start of enum VFSFileType Declaration */
+#define VFSFILETYPE_IID_STR "714333cd-44e2-415f-a245-d378fa9b1242"
+#define VFSFILETYPE_IID { \
+ 0x714333cd, 0x44e2, 0x415f, \
+ { 0xa2, 0x45, 0xd3, 0x78, 0xfa, 0x9b, 0x12, 0x42 } \
+}
+enum VFSFileType
+{
+ VFSFileType_Unknown = 1,
+ VFSFileType_Fifo = 2,
+ VFSFileType_DevChar = 3,
+ VFSFileType_Directory = 4,
+ VFSFileType_DevBlock = 5,
+ VFSFileType_File = 6,
+ VFSFileType_SymLink = 7,
+ VFSFileType_Socket = 8,
+ VFSFileType_WhiteOut = 9
+};
+/* End of enum VFSFileType Declaration */
+
+
+/* Start of enum ImportOptions Declaration */
+#define IMPORTOPTIONS_IID_STR "0a981523-3b20-4004-8ee3-dfd322202ace"
+#define IMPORTOPTIONS_IID { \
+ 0x0a981523, 0x3b20, 0x4004, \
+ { 0x8e, 0xe3, 0xdf, 0xd3, 0x22, 0x20, 0x2a, 0xce } \
+}
+enum ImportOptions
+{
+ ImportOptions_KeepAllMACs = 1,
+ ImportOptions_KeepNATMACs = 2
+};
+/* End of enum ImportOptions Declaration */
+
+
+/* Start of enum VirtualSystemDescriptionType Declaration */
+#define VIRTUALSYSTEMDESCRIPTIONTYPE_IID_STR "303c0900-a746-4612-8c67-79003e91f459"
+#define VIRTUALSYSTEMDESCRIPTIONTYPE_IID { \
+ 0x303c0900, 0xa746, 0x4612, \
+ { 0x8c, 0x67, 0x79, 0x00, 0x3e, 0x91, 0xf4, 0x59 } \
+}
+enum VirtualSystemDescriptionType
+{
+ VirtualSystemDescriptionType_Ignore = 1,
+ VirtualSystemDescriptionType_OS = 2,
+ VirtualSystemDescriptionType_Name = 3,
+ VirtualSystemDescriptionType_Product = 4,
+ VirtualSystemDescriptionType_Vendor = 5,
+ VirtualSystemDescriptionType_Version = 6,
+ VirtualSystemDescriptionType_ProductUrl = 7,
+ VirtualSystemDescriptionType_VendorUrl = 8,
+ VirtualSystemDescriptionType_Description = 9,
+ VirtualSystemDescriptionType_License = 10,
+ VirtualSystemDescriptionType_Miscellaneous = 11,
+ VirtualSystemDescriptionType_CPU = 12,
+ VirtualSystemDescriptionType_Memory = 13,
+ VirtualSystemDescriptionType_HardDiskControllerIDE = 14,
+ VirtualSystemDescriptionType_HardDiskControllerSATA = 15,
+ VirtualSystemDescriptionType_HardDiskControllerSCSI = 16,
+ VirtualSystemDescriptionType_HardDiskControllerSAS = 17,
+ VirtualSystemDescriptionType_HardDiskImage = 18,
+ VirtualSystemDescriptionType_Floppy = 19,
+ VirtualSystemDescriptionType_CDROM = 20,
+ VirtualSystemDescriptionType_NetworkAdapter = 21,
+ VirtualSystemDescriptionType_USBController = 22,
+ VirtualSystemDescriptionType_SoundCard = 23,
+ VirtualSystemDescriptionType_SettingsFile = 24
+};
+/* End of enum VirtualSystemDescriptionType Declaration */
+
+
+/* Start of enum VirtualSystemDescriptionValueType Declaration */
+#define VIRTUALSYSTEMDESCRIPTIONVALUETYPE_IID_STR "56d9403f-3425-4118-9919-36f2a9b8c77c"
+#define VIRTUALSYSTEMDESCRIPTIONVALUETYPE_IID { \
+ 0x56d9403f, 0x3425, 0x4118, \
+ { 0x99, 0x19, 0x36, 0xf2, 0xa9, 0xb8, 0xc7, 0x7c } \
+}
+enum VirtualSystemDescriptionValueType
+{
+ VirtualSystemDescriptionValueType_Reference = 1,
+ VirtualSystemDescriptionValueType_Original = 2,
+ VirtualSystemDescriptionValueType_Auto = 3,
+ VirtualSystemDescriptionValueType_ExtraConfig = 4
+};
+/* End of enum VirtualSystemDescriptionValueType Declaration */
+
+
+/* Start of enum CleanupMode Declaration */
+#define CLEANUPMODE_IID_STR "67897c50-7cca-47a9-83f6-ce8fd8eb5441"
+#define CLEANUPMODE_IID { \
+ 0x67897c50, 0x7cca, 0x47a9, \
+ { 0x83, 0xf6, 0xce, 0x8f, 0xd8, 0xeb, 0x54, 0x41 } \
+}
+enum CleanupMode
+{
+ CleanupMode_UnregisterOnly = 1,
+ CleanupMode_DetachAllReturnNone = 2,
+ CleanupMode_DetachAllReturnHardDisksOnly = 3,
+ CleanupMode_Full = 4
+};
+/* End of enum CleanupMode Declaration */
+
+
+/* Start of enum CloneMode Declaration */
+#define CLONEMODE_IID_STR "A7A159FE-5096-4B8D-8C3C-D033CB0B35A8"
+#define CLONEMODE_IID { \
+ 0xA7A159FE, 0x5096, 0x4B8D, \
+ { 0x8C, 0x3C, 0xD0, 0x33, 0xCB, 0x0B, 0x35, 0xA8 } \
+}
+enum CloneMode
+{
+ CloneMode_MachineState = 1,
+ CloneMode_MachineAndChildStates = 2,
+ CloneMode_AllStates = 3
+};
+/* End of enum CloneMode Declaration */
+
+
+/* Start of enum CloneOptions Declaration */
+#define CLONEOPTIONS_IID_STR "22243f8e-96ab-497c-8cf0-f40a566c630b"
+#define CLONEOPTIONS_IID { \
+ 0x22243f8e, 0x96ab, 0x497c, \
+ { 0x8c, 0xf0, 0xf4, 0x0a, 0x56, 0x6c, 0x63, 0x0b } \
+}
+enum CloneOptions
+{
+ CloneOptions_Link = 1,
+ CloneOptions_KeepAllMACs = 2,
+ CloneOptions_KeepNATMACs = 3,
+ CloneOptions_KeepDiskNames = 4
+};
+/* End of enum CloneOptions Declaration */
+
+
+/* Start of enum HostNetworkInterfaceMediumType Declaration */
+#define HOSTNETWORKINTERFACEMEDIUMTYPE_IID_STR "1aa54aaf-2497-45a2-bfb1-8eb225e93d5b"
+#define HOSTNETWORKINTERFACEMEDIUMTYPE_IID { \
+ 0x1aa54aaf, 0x2497, 0x45a2, \
+ { 0xbf, 0xb1, 0x8e, 0xb2, 0x25, 0xe9, 0x3d, 0x5b } \
+}
+enum HostNetworkInterfaceMediumType
+{
+ HostNetworkInterfaceMediumType_Unknown = 0,
+ HostNetworkInterfaceMediumType_Ethernet = 1,
+ HostNetworkInterfaceMediumType_PPP = 2,
+ HostNetworkInterfaceMediumType_SLIP = 3
+};
+/* End of enum HostNetworkInterfaceMediumType Declaration */
+
+
+/* Start of enum HostNetworkInterfaceStatus Declaration */
+#define HOSTNETWORKINTERFACESTATUS_IID_STR "CC474A69-2710-434B-8D99-C38E5D5A6F41"
+#define HOSTNETWORKINTERFACESTATUS_IID { \
+ 0xCC474A69, 0x2710, 0x434B, \
+ { 0x8D, 0x99, 0xC3, 0x8E, 0x5D, 0x5A, 0x6F, 0x41 } \
+}
+enum HostNetworkInterfaceStatus
+{
+ HostNetworkInterfaceStatus_Unknown = 0,
+ HostNetworkInterfaceStatus_Up = 1,
+ HostNetworkInterfaceStatus_Down = 2
+};
+/* End of enum HostNetworkInterfaceStatus Declaration */
+
+
+/* Start of enum HostNetworkInterfaceType Declaration */
+#define HOSTNETWORKINTERFACETYPE_IID_STR "67431b00-9946-48a2-bc02-b25c5919f4f3"
+#define HOSTNETWORKINTERFACETYPE_IID { \
+ 0x67431b00, 0x9946, 0x48a2, \
+ { 0xbc, 0x02, 0xb2, 0x5c, 0x59, 0x19, 0xf4, 0xf3 } \
+}
+enum HostNetworkInterfaceType
+{
+ HostNetworkInterfaceType_Bridged = 1,
+ HostNetworkInterfaceType_HostOnly = 2
+};
+/* End of enum HostNetworkInterfaceType Declaration */
+
+
+/* Start of enum AdditionsFacilityType Declaration */
+#define ADDITIONSFACILITYTYPE_IID_STR "98f7f957-89fb-49b6-a3b1-31e3285eb1d8"
+#define ADDITIONSFACILITYTYPE_IID { \
+ 0x98f7f957, 0x89fb, 0x49b6, \
+ { 0xa3, 0xb1, 0x31, 0xe3, 0x28, 0x5e, 0xb1, 0xd8 } \
+}
+enum AdditionsFacilityType
+{
+ AdditionsFacilityType_None = 0,
+ AdditionsFacilityType_VBoxGuestDriver = 20,
+ AdditionsFacilityType_VBoxService = 100,
+ AdditionsFacilityType_VBoxTrayClient = 101,
+ AdditionsFacilityType_Seamless = 1000,
+ AdditionsFacilityType_Graphics = 1100,
+ AdditionsFacilityType_All = 2147483646
+};
+/* End of enum AdditionsFacilityType Declaration */
+
+
+/* Start of enum AdditionsFacilityClass Declaration */
+#define ADDITIONSFACILITYCLASS_IID_STR "446451b2-c88d-4e5d-84c9-91bc7f533f5f"
+#define ADDITIONSFACILITYCLASS_IID { \
+ 0x446451b2, 0xc88d, 0x4e5d, \
+ { 0x84, 0xc9, 0x91, 0xbc, 0x7f, 0x53, 0x3f, 0x5f } \
+}
+enum AdditionsFacilityClass
+{
+ AdditionsFacilityClass_None = 0,
+ AdditionsFacilityClass_Driver = 10,
+ AdditionsFacilityClass_Service = 30,
+ AdditionsFacilityClass_Program = 50,
+ AdditionsFacilityClass_Feature = 100,
+ AdditionsFacilityClass_ThirdParty = 999,
+ AdditionsFacilityClass_All = 2147483646
+};
+/* End of enum AdditionsFacilityClass Declaration */
+
+
+/* Start of enum AdditionsFacilityStatus Declaration */
+#define ADDITIONSFACILITYSTATUS_IID_STR "ce06f9e1-394e-4fe9-9368-5a88c567dbde"
+#define ADDITIONSFACILITYSTATUS_IID { \
+ 0xce06f9e1, 0x394e, 0x4fe9, \
+ { 0x93, 0x68, 0x5a, 0x88, 0xc5, 0x67, 0xdb, 0xde } \
+}
+enum AdditionsFacilityStatus
+{
+ AdditionsFacilityStatus_Inactive = 0,
+ AdditionsFacilityStatus_Paused = 1,
+ AdditionsFacilityStatus_PreInit = 20,
+ AdditionsFacilityStatus_Init = 30,
+ AdditionsFacilityStatus_Active = 50,
+ AdditionsFacilityStatus_Terminating = 100,
+ AdditionsFacilityStatus_Terminated = 101,
+ AdditionsFacilityStatus_Failed = 800,
+ AdditionsFacilityStatus_Unknown = 999
+};
+/* End of enum AdditionsFacilityStatus Declaration */
+
+
+/* Start of enum AdditionsRunLevelType Declaration */
+#define ADDITIONSRUNLEVELTYPE_IID_STR "a25417ee-a9dd-4f5b-b0dc-377860087754"
+#define ADDITIONSRUNLEVELTYPE_IID { \
+ 0xa25417ee, 0xa9dd, 0x4f5b, \
+ { 0xb0, 0xdc, 0x37, 0x78, 0x60, 0x08, 0x77, 0x54 } \
+}
+enum AdditionsRunLevelType
+{
+ AdditionsRunLevelType_None = 0,
+ AdditionsRunLevelType_System = 1,
+ AdditionsRunLevelType_Userland = 2,
+ AdditionsRunLevelType_Desktop = 3
+};
+/* End of enum AdditionsRunLevelType Declaration */
+
+
+/* Start of enum AdditionsUpdateFlag Declaration */
+#define ADDITIONSUPDATEFLAG_IID_STR "726a818d-18d6-4389-94e8-3e9e6826171a"
+#define ADDITIONSUPDATEFLAG_IID { \
+ 0x726a818d, 0x18d6, 0x4389, \
+ { 0x94, 0xe8, 0x3e, 0x9e, 0x68, 0x26, 0x17, 0x1a } \
+}
+enum AdditionsUpdateFlag
+{
+ AdditionsUpdateFlag_None = 0,
+ AdditionsUpdateFlag_WaitForUpdateStartOnly = 1
+};
+/* End of enum AdditionsUpdateFlag Declaration */
+
+
+/* Start of enum ExecuteProcessFlag Declaration */
+#define EXECUTEPROCESSFLAG_IID_STR "286ceb91-5f66-4c96-9845-4483e90e00ae"
+#define EXECUTEPROCESSFLAG_IID { \
+ 0x286ceb91, 0x5f66, 0x4c96, \
+ { 0x98, 0x45, 0x44, 0x83, 0xe9, 0x0e, 0x00, 0xae } \
+}
+enum ExecuteProcessFlag
+{
+ ExecuteProcessFlag_None = 0,
+ ExecuteProcessFlag_WaitForProcessStartOnly = 1,
+ ExecuteProcessFlag_IgnoreOrphanedProcesses = 2,
+ ExecuteProcessFlag_Hidden = 4,
+ ExecuteProcessFlag_NoProfile = 8,
+ ExecuteProcessFlag_WaitForStdOut = 16,
+ ExecuteProcessFlag_WaitForStdErr = 32
+};
+/* End of enum ExecuteProcessFlag Declaration */
+
+
+/* Start of enum ExecuteProcessStatus Declaration */
+#define EXECUTEPROCESSSTATUS_IID_STR "153768d9-d971-4098-8b5a-c5cb1ab9ea88"
+#define EXECUTEPROCESSSTATUS_IID { \
+ 0x153768d9, 0xd971, 0x4098, \
+ { 0x8b, 0x5a, 0xc5, 0xcb, 0x1a, 0xb9, 0xea, 0x88 } \
+}
+enum ExecuteProcessStatus
+{
+ ExecuteProcessStatus_Undefined = 0,
+ ExecuteProcessStatus_Started = 1,
+ ExecuteProcessStatus_TerminatedNormally = 2,
+ ExecuteProcessStatus_TerminatedSignal = 3,
+ ExecuteProcessStatus_TerminatedAbnormally = 4,
+ ExecuteProcessStatus_TimedOutKilled = 5,
+ ExecuteProcessStatus_TimedOutAbnormally = 6,
+ ExecuteProcessStatus_Down = 7,
+ ExecuteProcessStatus_Error = 8
+};
+/* End of enum ExecuteProcessStatus Declaration */
+
+
+/* Start of enum ProcessInputFlag Declaration */
+#define PROCESSINPUTFLAG_IID_STR "5d38c1dd-2604-4ddf-92e5-0c0cdd3bdbd5"
+#define PROCESSINPUTFLAG_IID { \
+ 0x5d38c1dd, 0x2604, 0x4ddf, \
+ { 0x92, 0xe5, 0x0c, 0x0c, 0xdd, 0x3b, 0xdb, 0xd5 } \
+}
+enum ProcessInputFlag
+{
+ ProcessInputFlag_None = 0,
+ ProcessInputFlag_EndOfFile = 1
+};
+/* End of enum ProcessInputFlag Declaration */
+
+
+/* Start of enum ProcessOutputFlag Declaration */
+#define PROCESSOUTPUTFLAG_IID_STR "9979e85a-52bb-40b7-870c-57115e27e0f1"
+#define PROCESSOUTPUTFLAG_IID { \
+ 0x9979e85a, 0x52bb, 0x40b7, \
+ { 0x87, 0x0c, 0x57, 0x11, 0x5e, 0x27, 0xe0, 0xf1 } \
+}
+enum ProcessOutputFlag
+{
+ ProcessOutputFlag_None = 0,
+ ProcessOutputFlag_StdErr = 1
+};
+/* End of enum ProcessOutputFlag Declaration */
+
+
+/* Start of enum CopyFileFlag Declaration */
+#define COPYFILEFLAG_IID_STR "23f79fdf-738a-493d-b80b-42d607c9b916"
+#define COPYFILEFLAG_IID { \
+ 0x23f79fdf, 0x738a, 0x493d, \
+ { 0xb8, 0x0b, 0x42, 0xd6, 0x07, 0xc9, 0xb9, 0x16 } \
+}
+enum CopyFileFlag
+{
+ CopyFileFlag_None = 0,
+ CopyFileFlag_Recursive = 1,
+ CopyFileFlag_Update = 2,
+ CopyFileFlag_FollowLinks = 4
+};
+/* End of enum CopyFileFlag Declaration */
+
+
+/* Start of enum DirectoryCreateFlag Declaration */
+#define DIRECTORYCREATEFLAG_IID_STR "bd721b0e-ced5-4f79-b368-249897c32a36"
+#define DIRECTORYCREATEFLAG_IID { \
+ 0xbd721b0e, 0xced5, 0x4f79, \
+ { 0xb3, 0x68, 0x24, 0x98, 0x97, 0xc3, 0x2a, 0x36 } \
+}
+enum DirectoryCreateFlag
+{
+ DirectoryCreateFlag_None = 0,
+ DirectoryCreateFlag_Parents = 1
+};
+/* End of enum DirectoryCreateFlag Declaration */
+
+
+/* Start of enum DirectoryOpenFlag Declaration */
+#define DIRECTORYOPENFLAG_IID_STR "fc8f6203-0072-4f34-bd08-0b35e50bf071"
+#define DIRECTORYOPENFLAG_IID { \
+ 0xfc8f6203, 0x0072, 0x4f34, \
+ { 0xbd, 0x08, 0x0b, 0x35, 0xe5, 0x0b, 0xf0, 0x71 } \
+}
+enum DirectoryOpenFlag
+{
+ DirectoryOpenFlag_None = 0
+};
+/* End of enum DirectoryOpenFlag Declaration */
+
+
+/* Start of enum GuestDirEntryType Declaration */
+#define GUESTDIRENTRYTYPE_IID_STR "6d19d924-1b77-4fc8-b369-a3b2c85c8241"
+#define GUESTDIRENTRYTYPE_IID { \
+ 0x6d19d924, 0x1b77, 0x4fc8, \
+ { 0xb3, 0x69, 0xa3, 0xb2, 0xc8, 0x5c, 0x82, 0x41 } \
+}
+enum GuestDirEntryType
+{
+ GuestDirEntryType_Unknown = 0,
+ GuestDirEntryType_Directory = 4,
+ GuestDirEntryType_File = 10,
+ GuestDirEntryType_Symlink = 12
+};
+/* End of enum GuestDirEntryType Declaration */
+
+
+/* Start of enum MediumState Declaration */
+#define MEDIUMSTATE_IID_STR "ef41e980-e012-43cd-9dea-479d4ef14d13"
+#define MEDIUMSTATE_IID { \
+ 0xef41e980, 0xe012, 0x43cd, \
+ { 0x9d, 0xea, 0x47, 0x9d, 0x4e, 0xf1, 0x4d, 0x13 } \
+}
+enum MediumState
+{
+ MediumState_NotCreated = 0,
+ MediumState_Created = 1,
+ MediumState_LockedRead = 2,
+ MediumState_LockedWrite = 3,
+ MediumState_Inaccessible = 4,
+ MediumState_Creating = 5,
+ MediumState_Deleting = 6
+};
+/* End of enum MediumState Declaration */
+
+
+/* Start of enum MediumType Declaration */
+#define MEDIUMTYPE_IID_STR "fe663fb5-c244-4e1b-9d81-c628b417dd04"
+#define MEDIUMTYPE_IID { \
+ 0xfe663fb5, 0xc244, 0x4e1b, \
+ { 0x9d, 0x81, 0xc6, 0x28, 0xb4, 0x17, 0xdd, 0x04 } \
+}
+enum MediumType
+{
+ MediumType_Normal = 0,
+ MediumType_Immutable = 1,
+ MediumType_Writethrough = 2,
+ MediumType_Shareable = 3,
+ MediumType_Readonly = 4,
+ MediumType_MultiAttach = 5
+};
+/* End of enum MediumType Declaration */
+
+
+/* Start of enum MediumVariant Declaration */
+#define MEDIUMVARIANT_IID_STR "584ea502-143b-4ab0-ad14-d1028fdf0316"
+#define MEDIUMVARIANT_IID { \
+ 0x584ea502, 0x143b, 0x4ab0, \
+ { 0xad, 0x14, 0xd1, 0x02, 0x8f, 0xdf, 0x03, 0x16 } \
+}
+enum MediumVariant
+{
+ MediumVariant_Standard = 0,
+ MediumVariant_VmdkSplit2G = 0x01,
+ MediumVariant_VmdkStreamOptimized = 0x04,
+ MediumVariant_VmdkESX = 0x08,
+ MediumVariant_Fixed = 0x10000,
+ MediumVariant_Diff = 0x20000,
+ MediumVariant_NoCreateDir = 0x40000000
+};
+/* End of enum MediumVariant Declaration */
+
+
+/* Start of enum DataType Declaration */
+#define DATATYPE_IID_STR "d90ea51e-a3f1-4a01-beb1-c1723c0d3ba7"
+#define DATATYPE_IID { \
+ 0xd90ea51e, 0xa3f1, 0x4a01, \
+ { 0xbe, 0xb1, 0xc1, 0x72, 0x3c, 0x0d, 0x3b, 0xa7 } \
+}
+enum DataType
+{
+ DataType_Int32 = 0,
+ DataType_Int8 = 1,
+ DataType_String = 2
+};
+/* End of enum DataType Declaration */
+
+
+/* Start of enum DataFlags Declaration */
+#define DATAFLAGS_IID_STR "86884dcf-1d6b-4f1b-b4bf-f5aa44959d60"
+#define DATAFLAGS_IID { \
+ 0x86884dcf, 0x1d6b, 0x4f1b, \
+ { 0xb4, 0xbf, 0xf5, 0xaa, 0x44, 0x95, 0x9d, 0x60 } \
+}
+enum DataFlags
+{
+ DataFlags_None = 0x00,
+ DataFlags_Mandatory = 0x01,
+ DataFlags_Expert = 0x02,
+ DataFlags_Array = 0x04,
+ DataFlags_FlagMask = 0x07
+};
+/* End of enum DataFlags Declaration */
+
+
+/* Start of enum MediumFormatCapabilities Declaration */
+#define MEDIUMFORMATCAPABILITIES_IID_STR "7342ba79-7ce0-4d94-8f86-5ed5a185d9bd"
+#define MEDIUMFORMATCAPABILITIES_IID { \
+ 0x7342ba79, 0x7ce0, 0x4d94, \
+ { 0x8f, 0x86, 0x5e, 0xd5, 0xa1, 0x85, 0xd9, 0xbd } \
+}
+enum MediumFormatCapabilities
+{
+ MediumFormatCapabilities_Uuid = 0x01,
+ MediumFormatCapabilities_CreateFixed = 0x02,
+ MediumFormatCapabilities_CreateDynamic = 0x04,
+ MediumFormatCapabilities_CreateSplit2G = 0x08,
+ MediumFormatCapabilities_Differencing = 0x10,
+ MediumFormatCapabilities_Asynchronous = 0x20,
+ MediumFormatCapabilities_File = 0x40,
+ MediumFormatCapabilities_Properties = 0x80,
+ MediumFormatCapabilities_TcpNetworking = 0x100,
+ MediumFormatCapabilities_VFS = 0x200,
+ MediumFormatCapabilities_CapabilityMask = 0x3FF
+};
+/* End of enum MediumFormatCapabilities Declaration */
+
+
+/* Start of enum MouseButtonState Declaration */
+#define MOUSEBUTTONSTATE_IID_STR "9ee094b8-b28a-4d56-a166-973cb588d7f8"
+#define MOUSEBUTTONSTATE_IID { \
+ 0x9ee094b8, 0xb28a, 0x4d56, \
+ { 0xa1, 0x66, 0x97, 0x3c, 0xb5, 0x88, 0xd7, 0xf8 } \
+}
+enum MouseButtonState
+{
+ MouseButtonState_LeftButton = 0x01,
+ MouseButtonState_RightButton = 0x02,
+ MouseButtonState_MiddleButton = 0x04,
+ MouseButtonState_WheelUp = 0x08,
+ MouseButtonState_WheelDown = 0x10,
+ MouseButtonState_XButton1 = 0x20,
+ MouseButtonState_XButton2 = 0x40,
+ MouseButtonState_MouseStateMask = 0x7F
+};
+/* End of enum MouseButtonState Declaration */
+
+
+/* Start of enum FramebufferPixelFormat Declaration */
+#define FRAMEBUFFERPIXELFORMAT_IID_STR "7acfd5ed-29e3-45e3-8136-73c9224f3d2d"
+#define FRAMEBUFFERPIXELFORMAT_IID { \
+ 0x7acfd5ed, 0x29e3, 0x45e3, \
+ { 0x81, 0x36, 0x73, 0xc9, 0x22, 0x4f, 0x3d, 0x2d } \
+}
+enum FramebufferPixelFormat
+{
+ FramebufferPixelFormat_Opaque = 0,
+ FramebufferPixelFormat_FOURCC_RGB = 0x32424752
+};
+/* End of enum FramebufferPixelFormat Declaration */
+
+
+/* Start of enum NetworkAttachmentType Declaration */
+#define NETWORKATTACHMENTTYPE_IID_STR "2ac4bc71-6b82-417a-acd1-f7426d2570d6"
+#define NETWORKATTACHMENTTYPE_IID { \
+ 0x2ac4bc71, 0x6b82, 0x417a, \
+ { 0xac, 0xd1, 0xf7, 0x42, 0x6d, 0x25, 0x70, 0xd6 } \
+}
+enum NetworkAttachmentType
+{
+ NetworkAttachmentType_Null = 0,
+ NetworkAttachmentType_NAT = 1,
+ NetworkAttachmentType_Bridged = 2,
+ NetworkAttachmentType_Internal = 3,
+ NetworkAttachmentType_HostOnly = 4,
+ NetworkAttachmentType_Generic = 5
+};
+/* End of enum NetworkAttachmentType Declaration */
+
+
+/* Start of enum NetworkAdapterType Declaration */
+#define NETWORKADAPTERTYPE_IID_STR "3c2281e4-d952-4e87-8c7d-24379cb6a81c"
+#define NETWORKADAPTERTYPE_IID { \
+ 0x3c2281e4, 0xd952, 0x4e87, \
+ { 0x8c, 0x7d, 0x24, 0x37, 0x9c, 0xb6, 0xa8, 0x1c } \
+}
+enum NetworkAdapterType
+{
+ NetworkAdapterType_Null = 0,
+ NetworkAdapterType_Am79C970A = 1,
+ NetworkAdapterType_Am79C973 = 2,
+ NetworkAdapterType_I82540EM = 3,
+ NetworkAdapterType_I82543GC = 4,
+ NetworkAdapterType_I82545EM = 5,
+ NetworkAdapterType_Virtio = 6
+};
+/* End of enum NetworkAdapterType Declaration */
+
+
+/* Start of enum NetworkAdapterPromiscModePolicy Declaration */
+#define NETWORKADAPTERPROMISCMODEPOLICY_IID_STR "c963768a-376f-4c85-8d84-d8ced4b7269e"
+#define NETWORKADAPTERPROMISCMODEPOLICY_IID { \
+ 0xc963768a, 0x376f, 0x4c85, \
+ { 0x8d, 0x84, 0xd8, 0xce, 0xd4, 0xb7, 0x26, 0x9e } \
+}
+enum NetworkAdapterPromiscModePolicy
+{
+ NetworkAdapterPromiscModePolicy_Deny = 1,
+ NetworkAdapterPromiscModePolicy_AllowNetwork = 2,
+ NetworkAdapterPromiscModePolicy_AllowAll = 3
+};
+/* End of enum NetworkAdapterPromiscModePolicy Declaration */
+
+
+/* Start of enum PortMode Declaration */
+#define PORTMODE_IID_STR "533b5fe3-0185-4197-86a7-17e37dd39d76"
+#define PORTMODE_IID { \
+ 0x533b5fe3, 0x0185, 0x4197, \
+ { 0x86, 0xa7, 0x17, 0xe3, 0x7d, 0xd3, 0x9d, 0x76 } \
+}
+enum PortMode
+{
+ PortMode_Disconnected = 0,
+ PortMode_HostPipe = 1,
+ PortMode_HostDevice = 2,
+ PortMode_RawFile = 3
+};
+/* End of enum PortMode Declaration */
+
+
+/* Start of enum USBDeviceState Declaration */
+#define USBDEVICESTATE_IID_STR "b99a2e65-67fb-4882-82fd-f3e5e8193ab4"
+#define USBDEVICESTATE_IID { \
+ 0xb99a2e65, 0x67fb, 0x4882, \
+ { 0x82, 0xfd, 0xf3, 0xe5, 0xe8, 0x19, 0x3a, 0xb4 } \
+}
+enum USBDeviceState
+{
+ USBDeviceState_NotSupported = 0,
+ USBDeviceState_Unavailable = 1,
+ USBDeviceState_Busy = 2,
+ USBDeviceState_Available = 3,
+ USBDeviceState_Held = 4,
+ USBDeviceState_Captured = 5
+};
+/* End of enum USBDeviceState Declaration */
+
+
+/* Start of enum USBDeviceFilterAction Declaration */
+#define USBDEVICEFILTERACTION_IID_STR "cbc30a49-2f4e-43b5-9da6-121320475933"
+#define USBDEVICEFILTERACTION_IID { \
+ 0xcbc30a49, 0x2f4e, 0x43b5, \
+ { 0x9d, 0xa6, 0x12, 0x13, 0x20, 0x47, 0x59, 0x33 } \
+}
+enum USBDeviceFilterAction
+{
+ USBDeviceFilterAction_Null = 0,
+ USBDeviceFilterAction_Ignore = 1,
+ USBDeviceFilterAction_Hold = 2
+};
+/* End of enum USBDeviceFilterAction Declaration */
+
+
+/* Start of enum AudioDriverType Declaration */
+#define AUDIODRIVERTYPE_IID_STR "4bcc3d73-c2fe-40db-b72f-0c2ca9d68496"
+#define AUDIODRIVERTYPE_IID { \
+ 0x4bcc3d73, 0xc2fe, 0x40db, \
+ { 0xb7, 0x2f, 0x0c, 0x2c, 0xa9, 0xd6, 0x84, 0x96 } \
+}
+enum AudioDriverType
+{
+ AudioDriverType_Null = 0,
+ AudioDriverType_WinMM = 1,
+ AudioDriverType_OSS = 2,
+ AudioDriverType_ALSA = 3,
+ AudioDriverType_DirectSound = 4,
+ AudioDriverType_CoreAudio = 5,
+ AudioDriverType_MMPM = 6,
+ AudioDriverType_Pulse = 7,
+ AudioDriverType_SolAudio = 8
+};
+/* End of enum AudioDriverType Declaration */
+
+
+/* Start of enum AudioControllerType Declaration */
+#define AUDIOCONTROLLERTYPE_IID_STR "7afd395c-42c3-444e-8788-3ce80292f36c"
+#define AUDIOCONTROLLERTYPE_IID { \
+ 0x7afd395c, 0x42c3, 0x444e, \
+ { 0x87, 0x88, 0x3c, 0xe8, 0x02, 0x92, 0xf3, 0x6c } \
+}
+enum AudioControllerType
+{
+ AudioControllerType_AC97 = 0,
+ AudioControllerType_SB16 = 1,
+ AudioControllerType_HDA = 2
+};
+/* End of enum AudioControllerType Declaration */
+
+
+/* Start of enum AuthType Declaration */
+#define AUTHTYPE_IID_STR "7eef6ef6-98c2-4dc2-ab35-10d2b292028d"
+#define AUTHTYPE_IID { \
+ 0x7eef6ef6, 0x98c2, 0x4dc2, \
+ { 0xab, 0x35, 0x10, 0xd2, 0xb2, 0x92, 0x02, 0x8d } \
+}
+enum AuthType
+{
+ AuthType_Null = 0,
+ AuthType_External = 1,
+ AuthType_Guest = 2
+};
+/* End of enum AuthType Declaration */
+
+
+/* Start of enum StorageBus Declaration */
+#define STORAGEBUS_IID_STR "eee67ab3-668d-4ef5-91e0-7025fe4a0d7a"
+#define STORAGEBUS_IID { \
+ 0xeee67ab3, 0x668d, 0x4ef5, \
+ { 0x91, 0xe0, 0x70, 0x25, 0xfe, 0x4a, 0x0d, 0x7a } \
+}
+enum StorageBus
+{
+ StorageBus_Null = 0,
+ StorageBus_IDE = 1,
+ StorageBus_SATA = 2,
+ StorageBus_SCSI = 3,
+ StorageBus_Floppy = 4,
+ StorageBus_SAS = 5
+};
+/* End of enum StorageBus Declaration */
+
+
+/* Start of enum StorageControllerType Declaration */
+#define STORAGECONTROLLERTYPE_IID_STR "8a412b8a-f43e-4456-bd37-b474f0879a58"
+#define STORAGECONTROLLERTYPE_IID { \
+ 0x8a412b8a, 0xf43e, 0x4456, \
+ { 0xbd, 0x37, 0xb4, 0x74, 0xf0, 0x87, 0x9a, 0x58 } \
+}
+enum StorageControllerType
+{
+ StorageControllerType_Null = 0,
+ StorageControllerType_LsiLogic = 1,
+ StorageControllerType_BusLogic = 2,
+ StorageControllerType_IntelAhci = 3,
+ StorageControllerType_PIIX3 = 4,
+ StorageControllerType_PIIX4 = 5,
+ StorageControllerType_ICH6 = 6,
+ StorageControllerType_I82078 = 7,
+ StorageControllerType_LsiLogicSas = 8
+};
+/* End of enum StorageControllerType Declaration */
+
+
+/* Start of enum ChipsetType Declaration */
+#define CHIPSETTYPE_IID_STR "8b4096a8-a7c3-4d3b-bbb1-05a0a51ec394"
+#define CHIPSETTYPE_IID { \
+ 0x8b4096a8, 0xa7c3, 0x4d3b, \
+ { 0xbb, 0xb1, 0x05, 0xa0, 0xa5, 0x1e, 0xc3, 0x94 } \
+}
+enum ChipsetType
+{
+ ChipsetType_Null = 0,
+ ChipsetType_PIIX3 = 1,
+ ChipsetType_ICH9 = 2
+};
+/* End of enum ChipsetType Declaration */
+
+
+/* Start of enum NATAliasMode Declaration */
+#define NATALIASMODE_IID_STR "67772168-50d9-11df-9669-7fb714ee4fa1"
+#define NATALIASMODE_IID { \
+ 0x67772168, 0x50d9, 0x11df, \
+ { 0x96, 0x69, 0x7f, 0xb7, 0x14, 0xee, 0x4f, 0xa1 } \
+}
+enum NATAliasMode
+{
+ NATAliasMode_AliasLog = 0x1,
+ NATAliasMode_AliasProxyOnly = 0x02,
+ NATAliasMode_AliasUseSamePorts = 0x04
+};
+/* End of enum NATAliasMode Declaration */
+
+
+/* Start of enum NATProtocol Declaration */
+#define NATPROTOCOL_IID_STR "e90164be-eb03-11de-94af-fff9b1c1b19f"
+#define NATPROTOCOL_IID { \
+ 0xe90164be, 0xeb03, 0x11de, \
+ { 0x94, 0xaf, 0xff, 0xf9, 0xb1, 0xc1, 0xb1, 0x9f } \
+}
+enum NATProtocol
+{
+ NATProtocol_UDP = 0,
+ NATProtocol_TCP = 1
+};
+/* End of enum NATProtocol Declaration */
+
+
+/* Start of enum BandwidthGroupType Declaration */
+#define BANDWIDTHGROUPTYPE_IID_STR "1d92b67d-dc69-4be9-ad4c-93a01e1e0c8e"
+#define BANDWIDTHGROUPTYPE_IID { \
+ 0x1d92b67d, 0xdc69, 0x4be9, \
+ { 0xad, 0x4c, 0x93, 0xa0, 0x1e, 0x1e, 0x0c, 0x8e } \
+}
+enum BandwidthGroupType
+{
+ BandwidthGroupType_Null = 0,
+ BandwidthGroupType_Disk = 1,
+ BandwidthGroupType_Network = 2
+};
+/* End of enum BandwidthGroupType Declaration */
+
+
+/* Start of enum VBoxEventType Declaration */
+#define VBOXEVENTTYPE_IID_STR "cce48db6-8561-479d-8d46-1358bab45d4e"
+#define VBOXEVENTTYPE_IID { \
+ 0xcce48db6, 0x8561, 0x479d, \
+ { 0x8d, 0x46, 0x13, 0x58, 0xba, 0xb4, 0x5d, 0x4e } \
+}
+enum VBoxEventType
+{
+ VBoxEventType_Invalid = 0,
+ VBoxEventType_Any = 1,
+ VBoxEventType_Vetoable = 2,
+ VBoxEventType_MachineEvent = 3,
+ VBoxEventType_SnapshotEvent = 4,
+ VBoxEventType_InputEvent = 5,
+ VBoxEventType_LastWildcard = 31,
+ VBoxEventType_OnMachineStateChanged = 32,
+ VBoxEventType_OnMachineDataChanged = 33,
+ VBoxEventType_OnExtraDataChanged = 34,
+ VBoxEventType_OnExtraDataCanChange = 35,
+ VBoxEventType_OnMediumRegistered = 36,
+ VBoxEventType_OnMachineRegistered = 37,
+ VBoxEventType_OnSessionStateChanged = 38,
+ VBoxEventType_OnSnapshotTaken = 39,
+ VBoxEventType_OnSnapshotDeleted = 40,
+ VBoxEventType_OnSnapshotChanged = 41,
+ VBoxEventType_OnGuestPropertyChanged = 42,
+ VBoxEventType_OnMousePointerShapeChanged = 43,
+ VBoxEventType_OnMouseCapabilityChanged = 44,
+ VBoxEventType_OnKeyboardLedsChanged = 45,
+ VBoxEventType_OnStateChanged = 46,
+ VBoxEventType_OnAdditionsStateChanged = 47,
+ VBoxEventType_OnNetworkAdapterChanged = 48,
+ VBoxEventType_OnSerialPortChanged = 49,
+ VBoxEventType_OnParallelPortChanged = 50,
+ VBoxEventType_OnStorageControllerChanged = 51,
+ VBoxEventType_OnMediumChanged = 52,
+ VBoxEventType_OnVRDEServerChanged = 53,
+ VBoxEventType_OnUSBControllerChanged = 54,
+ VBoxEventType_OnUSBDeviceStateChanged = 55,
+ VBoxEventType_OnSharedFolderChanged = 56,
+ VBoxEventType_OnRuntimeError = 57,
+ VBoxEventType_OnCanShowWindow = 58,
+ VBoxEventType_OnShowWindow = 59,
+ VBoxEventType_OnCPUChanged = 60,
+ VBoxEventType_OnVRDEServerInfoChanged = 61,
+ VBoxEventType_OnEventSourceChanged = 62,
+ VBoxEventType_OnCPUExecutionCapChanged = 63,
+ VBoxEventType_OnGuestKeyboard = 64,
+ VBoxEventType_OnGuestMouse = 65,
+ VBoxEventType_OnNATRedirect = 66,
+ VBoxEventType_OnHostPciDevicePlug = 67,
+ VBoxEventType_OnVBoxSVCAvailabilityChanged = 68,
+ VBoxEventType_OnBandwidthGroupChanged = 69,
+ VBoxEventType_OnGuestMonitorChanged = 70,
+ VBoxEventType_OnStorageDeviceChanged = 71,
+ VBoxEventType_Last = 72
+};
+/* End of enum VBoxEventType Declaration */
+
+
+/* Start of enum GuestMonitorChangedEventType Declaration */
+#define GUESTMONITORCHANGEDEVENTTYPE_IID_STR "ef172985-7e36-4297-95be-e46396968d66"
+#define GUESTMONITORCHANGEDEVENTTYPE_IID { \
+ 0xef172985, 0x7e36, 0x4297, \
+ { 0x95, 0xbe, 0xe4, 0x63, 0x96, 0x96, 0x8d, 0x66 } \
+}
+enum GuestMonitorChangedEventType
+{
+ GuestMonitorChangedEventType_Enabled = 0,
+ GuestMonitorChangedEventType_Disabled = 1,
+ GuestMonitorChangedEventType_NewOrigin = 2
+};
+/* End of enum GuestMonitorChangedEventType Declaration */
+
+
+/* Start of struct IVirtualBoxErrorInfo Declaration */
+#define IVIRTUALBOXERRORINFO_IID_STR "e053d3c0-f493-491b-a735-3a9f0b1feed4"
+#define IVIRTUALBOXERRORINFO_IID { \
+ 0xe053d3c0, 0xf493, 0x491b, \
+ { 0xa7, 0x35, 0x3a, 0x9f, 0x0b, 0x1f, 0xee, 0xd4 } \
+}
+struct IVirtualBoxErrorInfo_vtbl
+{
+ struct nsIException_vtbl nsiexception;
+
+ nsresult (*GetResultCode)(IVirtualBoxErrorInfo *pThis, PRInt32 *resultCode);
+
+ nsresult (*GetInterfaceID)(IVirtualBoxErrorInfo *pThis, PRUnichar * *interfaceID);
+
+ nsresult (*GetComponent)(IVirtualBoxErrorInfo *pThis, PRUnichar * *component);
+
+ nsresult (*GetText)(IVirtualBoxErrorInfo *pThis, PRUnichar * *text);
+
+ nsresult (*GetNext)(IVirtualBoxErrorInfo *pThis, IVirtualBoxErrorInfo * *next);
+
+};
+
+struct IVirtualBoxErrorInfo
+{
+ struct IVirtualBoxErrorInfo_vtbl *vtbl;
+};
+/* End of struct IVirtualBoxErrorInfo Declaration */
+
+
+/* Start of struct IDHCPServer Declaration */
+#define IDHCPSERVER_IID_STR "6cfe387c-74fb-4ca7-bff6-973bec8af7a3"
+#define IDHCPSERVER_IID { \
+ 0x6cfe387c, 0x74fb, 0x4ca7, \
+ { 0xbf, 0xf6, 0x97, 0x3b, 0xec, 0x8a, 0xf7, 0xa3 } \
+}
+struct IDHCPServer_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetEnabled)(IDHCPServer *pThis, PRBool *enabled);
+ nsresult (*SetEnabled)(IDHCPServer *pThis, PRBool enabled);
+
+ nsresult (*GetIPAddress)(IDHCPServer *pThis, PRUnichar * *IPAddress);
+
+ nsresult (*GetNetworkMask)(IDHCPServer *pThis, PRUnichar * *networkMask);
+
+ nsresult (*GetNetworkName)(IDHCPServer *pThis, PRUnichar * *networkName);
+
+ nsresult (*GetLowerIP)(IDHCPServer *pThis, PRUnichar * *lowerIP);
+
+ nsresult (*GetUpperIP)(IDHCPServer *pThis, PRUnichar * *upperIP);
+
+ nsresult (*SetConfiguration)(
+ IDHCPServer *pThis,
+ PRUnichar * IPAddress,
+ PRUnichar * networkMask,
+ PRUnichar * FromIPAddress,
+ PRUnichar * ToIPAddress
+ );
+
+ nsresult (*Start)(
+ IDHCPServer *pThis,
+ PRUnichar * networkName,
+ PRUnichar * trunkName,
+ PRUnichar * trunkType
+ );
+
+ nsresult (*Stop)(IDHCPServer *pThis );
+
+};
+
+struct IDHCPServer
+{
+ struct IDHCPServer_vtbl *vtbl;
+};
+/* End of struct IDHCPServer Declaration */
+
+
+/* Start of struct IVirtualBox Declaration */
+#define IVIRTUALBOX_IID_STR "c28be65f-1a8f-43b4-81f1-eb60cb516e66"
+#define IVIRTUALBOX_IID { \
+ 0xc28be65f, 0x1a8f, 0x43b4, \
+ { 0x81, 0xf1, 0xeb, 0x60, 0xcb, 0x51, 0x6e, 0x66 } \
+}
+struct IVirtualBox_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetVersion)(IVirtualBox *pThis, PRUnichar * *version);
+
+ nsresult (*GetRevision)(IVirtualBox *pThis, PRUint32 *revision);
+
+ nsresult (*GetPackageType)(IVirtualBox *pThis, PRUnichar * *packageType);
+
+ nsresult (*GetAPIVersion)(IVirtualBox *pThis, PRUnichar * *APIVersion);
+
+ nsresult (*GetHomeFolder)(IVirtualBox *pThis, PRUnichar * *homeFolder);
+
+ nsresult (*GetSettingsFilePath)(IVirtualBox *pThis, PRUnichar * *settingsFilePath);
+
+ nsresult (*GetHost)(IVirtualBox *pThis, IHost * *host);
+
+ nsresult (*GetSystemProperties)(IVirtualBox *pThis, ISystemProperties * *systemProperties);
+
+ nsresult (*GetMachines)(IVirtualBox *pThis, PRUint32 *machinesSize, IMachine * **machines);
+
+ nsresult (*GetHardDisks)(IVirtualBox *pThis, PRUint32 *hardDisksSize, IMedium * **hardDisks);
+
+ nsresult (*GetDVDImages)(IVirtualBox *pThis, PRUint32 *DVDImagesSize, IMedium * **DVDImages);
+
+ nsresult (*GetFloppyImages)(IVirtualBox *pThis, PRUint32 *floppyImagesSize, IMedium * **floppyImages);
+
+ nsresult (*GetProgressOperations)(IVirtualBox *pThis, PRUint32 *progressOperationsSize, IProgress * **progressOperations);
+
+ nsresult (*GetGuestOSTypes)(IVirtualBox *pThis, PRUint32 *guestOSTypesSize, IGuestOSType * **guestOSTypes);
+
+ nsresult (*GetSharedFolders)(IVirtualBox *pThis, PRUint32 *sharedFoldersSize, ISharedFolder * **sharedFolders);
+
+ nsresult (*GetPerformanceCollector)(IVirtualBox *pThis, IPerformanceCollector * *performanceCollector);
+
+ nsresult (*GetDHCPServers)(IVirtualBox *pThis, PRUint32 *DHCPServersSize, IDHCPServer * **DHCPServers);
+
+ nsresult (*GetEventSource)(IVirtualBox *pThis, IEventSource * *eventSource);
+
+ nsresult (*GetExtensionPackManager)(IVirtualBox *pThis, IExtPackManager * *extensionPackManager);
+
+ nsresult (*GetInternalNetworks)(IVirtualBox *pThis, PRUint32 *internalNetworksSize, PRUnichar * **internalNetworks);
+
+ nsresult (*GetGenericNetworkDrivers)(IVirtualBox *pThis, PRUint32 *genericNetworkDriversSize, PRUnichar * **genericNetworkDrivers);
+
+ nsresult (*ComposeMachineFilename)(
+ IVirtualBox *pThis,
+ PRUnichar * name,
+ PRUnichar * baseFolder,
+ PRUnichar * * file
+ );
+
+ nsresult (*CreateMachine)(
+ IVirtualBox *pThis,
+ PRUnichar * settingsFile,
+ PRUnichar * name,
+ PRUnichar * osTypeId,
+ PRUnichar * id,
+ PRBool forceOverwrite,
+ IMachine * * machine
+ );
+
+ nsresult (*OpenMachine)(
+ IVirtualBox *pThis,
+ PRUnichar * settingsFile,
+ IMachine * * machine
+ );
+
+ nsresult (*RegisterMachine)(
+ IVirtualBox *pThis,
+ IMachine * machine
+ );
+
+ nsresult (*FindMachine)(
+ IVirtualBox *pThis,
+ PRUnichar * nameOrId,
+ IMachine * * machine
+ );
+
+ nsresult (*CreateAppliance)(
+ IVirtualBox *pThis,
+ IAppliance * * appliance
+ );
+
+ nsresult (*CreateHardDisk)(
+ IVirtualBox *pThis,
+ PRUnichar * format,
+ PRUnichar * location,
+ IMedium * * medium
+ );
+
+ nsresult (*OpenMedium)(
+ IVirtualBox *pThis,
+ PRUnichar * location,
+ PRUint32 deviceType,
+ PRUint32 accessMode,
+ PRBool forceNewUuid,
+ IMedium * * medium
+ );
+
+ nsresult (*FindMedium)(
+ IVirtualBox *pThis,
+ PRUnichar * location,
+ PRUint32 type,
+ IMedium * * medium
+ );
+
+ nsresult (*GetGuestOSType)(
+ IVirtualBox *pThis,
+ PRUnichar * id,
+ IGuestOSType * * type
+ );
+
+ nsresult (*CreateSharedFolder)(
+ IVirtualBox *pThis,
+ PRUnichar * name,
+ PRUnichar * hostPath,
+ PRBool writable,
+ PRBool automount
+ );
+
+ nsresult (*RemoveSharedFolder)(
+ IVirtualBox *pThis,
+ PRUnichar * name
+ );
+
+ nsresult (*GetExtraDataKeys)(
+ IVirtualBox *pThis,
+ PRUint32 *valueSize,
+ PRUnichar *** value
+ );
+
+ nsresult (*GetExtraData)(
+ IVirtualBox *pThis,
+ PRUnichar * key,
+ PRUnichar * * value
+ );
+
+ nsresult (*SetExtraData)(
+ IVirtualBox *pThis,
+ PRUnichar * key,
+ PRUnichar * value
+ );
+
+ nsresult (*CreateDHCPServer)(
+ IVirtualBox *pThis,
+ PRUnichar * name,
+ IDHCPServer * * server
+ );
+
+ nsresult (*FindDHCPServerByNetworkName)(
+ IVirtualBox *pThis,
+ PRUnichar * name,
+ IDHCPServer * * server
+ );
+
+ nsresult (*RemoveDHCPServer)(
+ IVirtualBox *pThis,
+ IDHCPServer * server
+ );
+
+ nsresult (*CheckFirmwarePresent)(
+ IVirtualBox *pThis,
+ PRUint32 firmwareType,
+ PRUnichar * version,
+ PRUnichar * * url,
+ PRUnichar * * file,
+ PRBool * result
+ );
+
+};
+
+struct IVirtualBox
+{
+ struct IVirtualBox_vtbl *vtbl;
+};
+/* End of struct IVirtualBox Declaration */
+
+
+/* Start of struct IVFSExplorer Declaration */
+#define IVFSEXPLORER_IID_STR "003d7f92-d38e-487f-b790-8c5e8631cb2f"
+#define IVFSEXPLORER_IID { \
+ 0x003d7f92, 0xd38e, 0x487f, \
+ { 0xb7, 0x90, 0x8c, 0x5e, 0x86, 0x31, 0xcb, 0x2f } \
+}
+struct IVFSExplorer_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetPath)(IVFSExplorer *pThis, PRUnichar * *path);
+
+ nsresult (*GetType)(IVFSExplorer *pThis, PRUint32 *type);
+
+ nsresult (*Update)(
+ IVFSExplorer *pThis,
+ IProgress * * aProgress
+ );
+
+ nsresult (*Cd)(
+ IVFSExplorer *pThis,
+ PRUnichar * aDir,
+ IProgress * * aProgress
+ );
+
+ nsresult (*CdUp)(
+ IVFSExplorer *pThis,
+ IProgress * * aProgress
+ );
+
+ nsresult (*EntryList)(
+ IVFSExplorer *pThis,
+ PRUint32 *aNamesSize,
+ PRUnichar *** aNames,
+ PRUint32 *aTypesSize,
+ PRUint32* aTypes,
+ PRUint32 *aSizesSize,
+ PRUint32* aSizes,
+ PRUint32 *aModesSize,
+ PRUint32* aModes
+ );
+
+ nsresult (*Exists)(
+ IVFSExplorer *pThis,
+ PRUint32 aNamesSize,
+ PRUnichar ** aNames,
+ PRUint32 *aExistsSize,
+ PRUnichar *** aExists
+ );
+
+ nsresult (*Remove)(
+ IVFSExplorer *pThis,
+ PRUint32 aNamesSize,
+ PRUnichar ** aNames,
+ IProgress * * aProgress
+ );
+
+};
+
+struct IVFSExplorer
+{
+ struct IVFSExplorer_vtbl *vtbl;
+};
+/* End of struct IVFSExplorer Declaration */
+
+
+/* Start of struct IAppliance Declaration */
+#define IAPPLIANCE_IID_STR "3059cf9e-25c7-4f0b-9fa5-3c42e441670b"
+#define IAPPLIANCE_IID { \
+ 0x3059cf9e, 0x25c7, 0x4f0b, \
+ { 0x9f, 0xa5, 0x3c, 0x42, 0xe4, 0x41, 0x67, 0x0b } \
+}
+struct IAppliance_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetPath)(IAppliance *pThis, PRUnichar * *path);
+
+ nsresult (*GetDisks)(IAppliance *pThis, PRUint32 *disksSize, PRUnichar * **disks);
+
+ nsresult (*GetVirtualSystemDescriptions)(IAppliance *pThis, PRUint32 *virtualSystemDescriptionsSize, IVirtualSystemDescription * **virtualSystemDescriptions);
+
+ nsresult (*GetMachines)(IAppliance *pThis, PRUint32 *machinesSize, PRUnichar * **machines);
+
+ nsresult (*Read)(
+ IAppliance *pThis,
+ PRUnichar * file,
+ IProgress * * aProgress
+ );
+
+ nsresult (*Interpret)(IAppliance *pThis );
+
+ nsresult (*ImportMachines)(
+ IAppliance *pThis,
+ PRUint32 optionsSize,
+ PRUint32* options,
+ IProgress * * aProgress
+ );
+
+ nsresult (*CreateVFSExplorer)(
+ IAppliance *pThis,
+ PRUnichar * aUri,
+ IVFSExplorer * * aExplorer
+ );
+
+ nsresult (*Write)(
+ IAppliance *pThis,
+ PRUnichar * format,
+ PRBool manifest,
+ PRUnichar * path,
+ IProgress * * progress
+ );
+
+ nsresult (*GetWarnings)(
+ IAppliance *pThis,
+ PRUint32 *aWarningsSize,
+ PRUnichar *** aWarnings
+ );
+
+};
+
+struct IAppliance
+{
+ struct IAppliance_vtbl *vtbl;
+};
+/* End of struct IAppliance Declaration */
+
+
+/* Start of struct IVirtualSystemDescription Declaration */
+#define IVIRTUALSYSTEMDESCRIPTION_IID_STR "d7525e6c-531a-4c51-8e04-41235083a3d8"
+#define IVIRTUALSYSTEMDESCRIPTION_IID { \
+ 0xd7525e6c, 0x531a, 0x4c51, \
+ { 0x8e, 0x04, 0x41, 0x23, 0x50, 0x83, 0xa3, 0xd8 } \
+}
+struct IVirtualSystemDescription_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetCount)(IVirtualSystemDescription *pThis, PRUint32 *count);
+
+ nsresult (*GetDescription)(
+ IVirtualSystemDescription *pThis,
+ PRUint32 *aTypesSize,
+ PRUint32* aTypes,
+ PRUint32 *aRefsSize,
+ PRUnichar *** aRefs,
+ PRUint32 *aOvfValuesSize,
+ PRUnichar *** aOvfValues,
+ PRUint32 *aVBoxValuesSize,
+ PRUnichar *** aVBoxValues,
+ PRUint32 *aExtraConfigValuesSize,
+ PRUnichar *** aExtraConfigValues
+ );
+
+ nsresult (*GetDescriptionByType)(
+ IVirtualSystemDescription *pThis,
+ PRUint32 aType,
+ PRUint32 *aTypesSize,
+ PRUint32* aTypes,
+ PRUint32 *aRefsSize,
+ PRUnichar *** aRefs,
+ PRUint32 *aOvfValuesSize,
+ PRUnichar *** aOvfValues,
+ PRUint32 *aVBoxValuesSize,
+ PRUnichar *** aVBoxValues,
+ PRUint32 *aExtraConfigValuesSize,
+ PRUnichar *** aExtraConfigValues
+ );
+
+ nsresult (*GetValuesByType)(
+ IVirtualSystemDescription *pThis,
+ PRUint32 aType,
+ PRUint32 aWhich,
+ PRUint32 *aValuesSize,
+ PRUnichar *** aValues
+ );
+
+ nsresult (*SetFinalValues)(
+ IVirtualSystemDescription *pThis,
+ PRUint32 aEnabledSize,
+ PRBool* aEnabled,
+ PRUint32 aVBoxValuesSize,
+ PRUnichar ** aVBoxValues,
+ PRUint32 aExtraConfigValuesSize,
+ PRUnichar ** aExtraConfigValues
+ );
+
+ nsresult (*AddDescription)(
+ IVirtualSystemDescription *pThis,
+ PRUint32 aType,
+ PRUnichar * aVBoxValue,
+ PRUnichar * aExtraConfigValue
+ );
+
+};
+
+struct IVirtualSystemDescription
+{
+ struct IVirtualSystemDescription_vtbl *vtbl;
+};
+/* End of struct IVirtualSystemDescription Declaration */
+
+
+/* Start of struct IInternalMachineControl Declaration */
+#define IINTERNALMACHINECONTROL_IID_STR "2087906d-bb92-43a0-8014-4cab009e4888"
+#define IINTERNALMACHINECONTROL_IID { \
+ 0x2087906d, 0xbb92, 0x43a0, \
+ { 0x80, 0x14, 0x4c, 0xab, 0x00, 0x9e, 0x48, 0x88 } \
+}
+struct IInternalMachineControl_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*SetRemoveSavedStateFile)(
+ IInternalMachineControl *pThis,
+ PRBool aRemove
+ );
+
+ nsresult (*UpdateState)(
+ IInternalMachineControl *pThis,
+ PRUint32 state
+ );
+
+ nsresult (*GetIPCId)(
+ IInternalMachineControl *pThis,
+ PRUnichar * * id
+ );
+
+ nsresult (*BeginPowerUp)(
+ IInternalMachineControl *pThis,
+ IProgress * aProgress
+ );
+
+ nsresult (*EndPowerUp)(
+ IInternalMachineControl *pThis,
+ PRInt32 result
+ );
+
+ nsresult (*BeginPoweringDown)(
+ IInternalMachineControl *pThis,
+ IProgress * * progress
+ );
+
+ nsresult (*EndPoweringDown)(
+ IInternalMachineControl *pThis,
+ PRInt32 result,
+ PRUnichar * errMsg
+ );
+
+ nsresult (*RunUSBDeviceFilters)(
+ IInternalMachineControl *pThis,
+ IUSBDevice * device,
+ PRBool * matched,
+ PRUint32 * maskedInterfaces
+ );
+
+ nsresult (*CaptureUSBDevice)(
+ IInternalMachineControl *pThis,
+ PRUnichar * id
+ );
+
+ nsresult (*DetachUSBDevice)(
+ IInternalMachineControl *pThis,
+ PRUnichar * id,
+ PRBool done
+ );
+
+ nsresult (*AutoCaptureUSBDevices)(IInternalMachineControl *pThis );
+
+ nsresult (*DetachAllUSBDevices)(
+ IInternalMachineControl *pThis,
+ PRBool done
+ );
+
+ nsresult (*OnSessionEnd)(
+ IInternalMachineControl *pThis,
+ ISession * session,
+ IProgress * * progress
+ );
+
+ nsresult (*BeginSavingState)(
+ IInternalMachineControl *pThis,
+ IProgress * * progress,
+ PRUnichar * * stateFilePath
+ );
+
+ nsresult (*EndSavingState)(
+ IInternalMachineControl *pThis,
+ PRInt32 result,
+ PRUnichar * errMsg
+ );
+
+ nsresult (*AdoptSavedState)(
+ IInternalMachineControl *pThis,
+ PRUnichar * savedStateFile
+ );
+
+ nsresult (*BeginTakingSnapshot)(
+ IInternalMachineControl *pThis,
+ IConsole * initiator,
+ PRUnichar * name,
+ PRUnichar * description,
+ IProgress * consoleProgress,
+ PRBool fTakingSnapshotOnline,
+ PRUnichar * * stateFilePath
+ );
+
+ nsresult (*EndTakingSnapshot)(
+ IInternalMachineControl *pThis,
+ PRBool success
+ );
+
+ nsresult (*DeleteSnapshot)(
+ IInternalMachineControl *pThis,
+ IConsole * initiator,
+ PRUnichar * startId,
+ PRUnichar * endId,
+ PRBool deleteAllChildren,
+ PRUint32 * machineState,
+ IProgress * * progress
+ );
+
+ nsresult (*FinishOnlineMergeMedium)(
+ IInternalMachineControl *pThis,
+ IMediumAttachment * mediumAttachment,
+ IMedium * source,
+ IMedium * target,
+ PRBool mergeForward,
+ IMedium * parentForTarget,
+ PRUint32 childrenToReparentSize,
+ IMedium ** childrenToReparent
+ );
+
+ nsresult (*RestoreSnapshot)(
+ IInternalMachineControl *pThis,
+ IConsole * initiator,
+ ISnapshot * snapshot,
+ PRUint32 * machineState,
+ IProgress * * progress
+ );
+
+ nsresult (*PullGuestProperties)(
+ IInternalMachineControl *pThis,
+ PRUint32 *nameSize,
+ PRUnichar *** name,
+ PRUint32 *valueSize,
+ PRUnichar *** value,
+ PRUint32 *timestampSize,
+ PRInt64* timestamp,
+ PRUint32 *flagsSize,
+ PRUnichar *** flags
+ );
+
+ nsresult (*PushGuestProperty)(
+ IInternalMachineControl *pThis,
+ PRUnichar * name,
+ PRUnichar * value,
+ PRInt64 timestamp,
+ PRUnichar * flags
+ );
+
+ nsresult (*LockMedia)(IInternalMachineControl *pThis );
+
+ nsresult (*UnlockMedia)(IInternalMachineControl *pThis );
+
+ nsresult (*EjectMedium)(
+ IInternalMachineControl *pThis,
+ IMediumAttachment * attachment,
+ IMediumAttachment * * newAttachment
+ );
+
+};
+
+struct IInternalMachineControl
+{
+ struct IInternalMachineControl_vtbl *vtbl;
+};
+/* End of struct IInternalMachineControl Declaration */
+
+
+/* Start of struct IBIOSSettings Declaration */
+#define IBIOSSETTINGS_IID_STR "38b54279-dc35-4f5e-a431-835b867c6b5e"
+#define IBIOSSETTINGS_IID { \
+ 0x38b54279, 0xdc35, 0x4f5e, \
+ { 0xa4, 0x31, 0x83, 0x5b, 0x86, 0x7c, 0x6b, 0x5e } \
+}
+struct IBIOSSettings_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetLogoFadeIn)(IBIOSSettings *pThis, PRBool *logoFadeIn);
+ nsresult (*SetLogoFadeIn)(IBIOSSettings *pThis, PRBool logoFadeIn);
+
+ nsresult (*GetLogoFadeOut)(IBIOSSettings *pThis, PRBool *logoFadeOut);
+ nsresult (*SetLogoFadeOut)(IBIOSSettings *pThis, PRBool logoFadeOut);
+
+ nsresult (*GetLogoDisplayTime)(IBIOSSettings *pThis, PRUint32 *logoDisplayTime);
+ nsresult (*SetLogoDisplayTime)(IBIOSSettings *pThis, PRUint32 logoDisplayTime);
+
+ nsresult (*GetLogoImagePath)(IBIOSSettings *pThis, PRUnichar * *logoImagePath);
+ nsresult (*SetLogoImagePath)(IBIOSSettings *pThis, PRUnichar * logoImagePath);
+
+ nsresult (*GetBootMenuMode)(IBIOSSettings *pThis, PRUint32 *bootMenuMode);
+ nsresult (*SetBootMenuMode)(IBIOSSettings *pThis, PRUint32 bootMenuMode);
+
+ nsresult (*GetACPIEnabled)(IBIOSSettings *pThis, PRBool *ACPIEnabled);
+ nsresult (*SetACPIEnabled)(IBIOSSettings *pThis, PRBool ACPIEnabled);
+
+ nsresult (*GetIOAPICEnabled)(IBIOSSettings *pThis, PRBool *IOAPICEnabled);
+ nsresult (*SetIOAPICEnabled)(IBIOSSettings *pThis, PRBool IOAPICEnabled);
+
+ nsresult (*GetTimeOffset)(IBIOSSettings *pThis, PRInt64 *timeOffset);
+ nsresult (*SetTimeOffset)(IBIOSSettings *pThis, PRInt64 timeOffset);
+
+ nsresult (*GetPXEDebugEnabled)(IBIOSSettings *pThis, PRBool *PXEDebugEnabled);
+ nsresult (*SetPXEDebugEnabled)(IBIOSSettings *pThis, PRBool PXEDebugEnabled);
+
+};
+
+struct IBIOSSettings
+{
+ struct IBIOSSettings_vtbl *vtbl;
+};
+/* End of struct IBIOSSettings Declaration */
+
+
+/* Start of struct IPciAddress Declaration */
+#define IPCIADDRESS_IID_STR "D88B324F-DB19-4D3B-A1A9-BF5B127199A8"
+#define IPCIADDRESS_IID { \
+ 0xD88B324F, 0xDB19, 0x4D3B, \
+ { 0xA1, 0xA9, 0xBF, 0x5B, 0x12, 0x71, 0x99, 0xA8 } \
+}
+struct IPciAddress_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetBus)(IPciAddress *pThis, PRInt16 *bus);
+ nsresult (*SetBus)(IPciAddress *pThis, PRInt16 bus);
+
+ nsresult (*GetDevice)(IPciAddress *pThis, PRInt16 *device);
+ nsresult (*SetDevice)(IPciAddress *pThis, PRInt16 device);
+
+ nsresult (*GetDevFunction)(IPciAddress *pThis, PRInt16 *devFunction);
+ nsresult (*SetDevFunction)(IPciAddress *pThis, PRInt16 devFunction);
+
+ nsresult (*AsLong)(
+ IPciAddress *pThis,
+ PRInt32 * result
+ );
+
+ nsresult (*FromLong)(
+ IPciAddress *pThis,
+ PRInt32 number
+ );
+
+};
+
+struct IPciAddress
+{
+ struct IPciAddress_vtbl *vtbl;
+};
+/* End of struct IPciAddress Declaration */
+
+
+/* Start of struct IPciDeviceAttachment Declaration */
+#define IPCIDEVICEATTACHMENT_IID_STR "91f33d6f-e621-4f70-a77e-15f0e3c714d5"
+#define IPCIDEVICEATTACHMENT_IID { \
+ 0x91f33d6f, 0xe621, 0x4f70, \
+ { 0xa7, 0x7e, 0x15, 0xf0, 0xe3, 0xc7, 0x14, 0xd5 } \
+}
+struct IPciDeviceAttachment_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetName)(IPciDeviceAttachment *pThis, PRUnichar * *name);
+
+ nsresult (*GetIsPhysicalDevice)(IPciDeviceAttachment *pThis, PRBool *isPhysicalDevice);
+
+ nsresult (*GetHostAddress)(IPciDeviceAttachment *pThis, PRInt32 *hostAddress);
+
+ nsresult (*GetGuestAddress)(IPciDeviceAttachment *pThis, PRInt32 *guestAddress);
+
+};
+
+struct IPciDeviceAttachment
+{
+ struct IPciDeviceAttachment_vtbl *vtbl;
+};
+/* End of struct IPciDeviceAttachment Declaration */
+
+
+/* Start of struct IMachine Declaration */
+#define IMACHINE_IID_STR "5eaa9319-62fc-4b0a-843c-0cb1940f8a91"
+#define IMACHINE_IID { \
+ 0x5eaa9319, 0x62fc, 0x4b0a, \
+ { 0x84, 0x3c, 0x0c, 0xb1, 0x94, 0x0f, 0x8a, 0x91 } \
+}
+struct IMachine_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetParent)(IMachine *pThis, IVirtualBox * *parent);
+
+ nsresult (*GetAccessible)(IMachine *pThis, PRBool *accessible);
+
+ nsresult (*GetAccessError)(IMachine *pThis, IVirtualBoxErrorInfo * *accessError);
+
+ nsresult (*GetName)(IMachine *pThis, PRUnichar * *name);
+ nsresult (*SetName)(IMachine *pThis, PRUnichar * name);
+
+ nsresult (*GetDescription)(IMachine *pThis, PRUnichar * *description);
+ nsresult (*SetDescription)(IMachine *pThis, PRUnichar * description);
+
+ nsresult (*GetId)(IMachine *pThis, PRUnichar * *id);
+
+ nsresult (*GetOSTypeId)(IMachine *pThis, PRUnichar * *OSTypeId);
+ nsresult (*SetOSTypeId)(IMachine *pThis, PRUnichar * OSTypeId);
+
+ nsresult (*GetHardwareVersion)(IMachine *pThis, PRUnichar * *hardwareVersion);
+ nsresult (*SetHardwareVersion)(IMachine *pThis, PRUnichar * hardwareVersion);
+
+ nsresult (*GetHardwareUUID)(IMachine *pThis, PRUnichar * *hardwareUUID);
+ nsresult (*SetHardwareUUID)(IMachine *pThis, PRUnichar * hardwareUUID);
+
+ nsresult (*GetCPUCount)(IMachine *pThis, PRUint32 *CPUCount);
+ nsresult (*SetCPUCount)(IMachine *pThis, PRUint32 CPUCount);
+
+ nsresult (*GetCPUHotPlugEnabled)(IMachine *pThis, PRBool *CPUHotPlugEnabled);
+ nsresult (*SetCPUHotPlugEnabled)(IMachine *pThis, PRBool CPUHotPlugEnabled);
+
+ nsresult (*GetCPUExecutionCap)(IMachine *pThis, PRUint32 *CPUExecutionCap);
+ nsresult (*SetCPUExecutionCap)(IMachine *pThis, PRUint32 CPUExecutionCap);
+
+ nsresult (*GetMemorySize)(IMachine *pThis, PRUint32 *memorySize);
+ nsresult (*SetMemorySize)(IMachine *pThis, PRUint32 memorySize);
+
+ nsresult (*GetMemoryBalloonSize)(IMachine *pThis, PRUint32 *memoryBalloonSize);
+ nsresult (*SetMemoryBalloonSize)(IMachine *pThis, PRUint32 memoryBalloonSize);
+
+ nsresult (*GetPageFusionEnabled)(IMachine *pThis, PRBool *pageFusionEnabled);
+ nsresult (*SetPageFusionEnabled)(IMachine *pThis, PRBool pageFusionEnabled);
+
+ nsresult (*GetVRAMSize)(IMachine *pThis, PRUint32 *VRAMSize);
+ nsresult (*SetVRAMSize)(IMachine *pThis, PRUint32 VRAMSize);
+
+ nsresult (*GetAccelerate3DEnabled)(IMachine *pThis, PRBool *accelerate3DEnabled);
+ nsresult (*SetAccelerate3DEnabled)(IMachine *pThis, PRBool accelerate3DEnabled);
+
+ nsresult (*GetAccelerate2DVideoEnabled)(IMachine *pThis, PRBool *accelerate2DVideoEnabled);
+ nsresult (*SetAccelerate2DVideoEnabled)(IMachine *pThis, PRBool accelerate2DVideoEnabled);
+
+ nsresult (*GetMonitorCount)(IMachine *pThis, PRUint32 *monitorCount);
+ nsresult (*SetMonitorCount)(IMachine *pThis, PRUint32 monitorCount);
+
+ nsresult (*GetBIOSSettings)(IMachine *pThis, IBIOSSettings * *BIOSSettings);
+
+ nsresult (*GetFirmwareType)(IMachine *pThis, PRUint32 *firmwareType);
+ nsresult (*SetFirmwareType)(IMachine *pThis, PRUint32 firmwareType);
+
+ nsresult (*GetPointingHidType)(IMachine *pThis, PRUint32 *pointingHidType);
+ nsresult (*SetPointingHidType)(IMachine *pThis, PRUint32 pointingHidType);
+
+ nsresult (*GetKeyboardHidType)(IMachine *pThis, PRUint32 *keyboardHidType);
+ nsresult (*SetKeyboardHidType)(IMachine *pThis, PRUint32 keyboardHidType);
+
+ nsresult (*GetHpetEnabled)(IMachine *pThis, PRBool *hpetEnabled);
+ nsresult (*SetHpetEnabled)(IMachine *pThis, PRBool hpetEnabled);
+
+ nsresult (*GetChipsetType)(IMachine *pThis, PRUint32 *chipsetType);
+ nsresult (*SetChipsetType)(IMachine *pThis, PRUint32 chipsetType);
+
+ nsresult (*GetSnapshotFolder)(IMachine *pThis, PRUnichar * *snapshotFolder);
+ nsresult (*SetSnapshotFolder)(IMachine *pThis, PRUnichar * snapshotFolder);
+
+ nsresult (*GetVRDEServer)(IMachine *pThis, IVRDEServer * *VRDEServer);
+
+ nsresult (*GetEmulatedUSBWebcameraEnabled)(IMachine *pThis, PRBool *emulatedUSBWebcameraEnabled);
+ nsresult (*SetEmulatedUSBWebcameraEnabled)(IMachine *pThis, PRBool emulatedUSBWebcameraEnabled);
+
+ nsresult (*GetEmulatedUSBCardReaderEnabled)(IMachine *pThis, PRBool *emulatedUSBCardReaderEnabled);
+ nsresult (*SetEmulatedUSBCardReaderEnabled)(IMachine *pThis, PRBool emulatedUSBCardReaderEnabled);
+
+ nsresult (*GetMediumAttachments)(IMachine *pThis, PRUint32 *mediumAttachmentsSize, IMediumAttachment * **mediumAttachments);
+
+ nsresult (*GetUSBController)(IMachine *pThis, IUSBController * *USBController);
+
+ nsresult (*GetAudioAdapter)(IMachine *pThis, IAudioAdapter * *audioAdapter);
+
+ nsresult (*GetStorageControllers)(IMachine *pThis, PRUint32 *storageControllersSize, IStorageController * **storageControllers);
+
+ nsresult (*GetSettingsFilePath)(IMachine *pThis, PRUnichar * *settingsFilePath);
+
+ nsresult (*GetSettingsModified)(IMachine *pThis, PRBool *settingsModified);
+
+ nsresult (*GetSessionState)(IMachine *pThis, PRUint32 *sessionState);
+
+ nsresult (*GetSessionType)(IMachine *pThis, PRUnichar * *sessionType);
+
+ nsresult (*GetSessionPid)(IMachine *pThis, PRUint32 *sessionPid);
+
+ nsresult (*GetState)(IMachine *pThis, PRUint32 *state);
+
+ nsresult (*GetLastStateChange)(IMachine *pThis, PRInt64 *lastStateChange);
+
+ nsresult (*GetStateFilePath)(IMachine *pThis, PRUnichar * *stateFilePath);
+
+ nsresult (*GetLogFolder)(IMachine *pThis, PRUnichar * *logFolder);
+
+ nsresult (*GetCurrentSnapshot)(IMachine *pThis, ISnapshot * *currentSnapshot);
+
+ nsresult (*GetSnapshotCount)(IMachine *pThis, PRUint32 *snapshotCount);
+
+ nsresult (*GetCurrentStateModified)(IMachine *pThis, PRBool *currentStateModified);
+
+ nsresult (*GetSharedFolders)(IMachine *pThis, PRUint32 *sharedFoldersSize, ISharedFolder * **sharedFolders);
+
+ nsresult (*GetClipboardMode)(IMachine *pThis, PRUint32 *clipboardMode);
+ nsresult (*SetClipboardMode)(IMachine *pThis, PRUint32 clipboardMode);
+
+ nsresult (*GetGuestPropertyNotificationPatterns)(IMachine *pThis, PRUnichar * *guestPropertyNotificationPatterns);
+ nsresult (*SetGuestPropertyNotificationPatterns)(IMachine *pThis, PRUnichar * guestPropertyNotificationPatterns);
+
+ nsresult (*GetTeleporterEnabled)(IMachine *pThis, PRBool *teleporterEnabled);
+ nsresult (*SetTeleporterEnabled)(IMachine *pThis, PRBool teleporterEnabled);
+
+ nsresult (*GetTeleporterPort)(IMachine *pThis, PRUint32 *teleporterPort);
+ nsresult (*SetTeleporterPort)(IMachine *pThis, PRUint32 teleporterPort);
+
+ nsresult (*GetTeleporterAddress)(IMachine *pThis, PRUnichar * *teleporterAddress);
+ nsresult (*SetTeleporterAddress)(IMachine *pThis, PRUnichar * teleporterAddress);
+
+ nsresult (*GetTeleporterPassword)(IMachine *pThis, PRUnichar * *teleporterPassword);
+ nsresult (*SetTeleporterPassword)(IMachine *pThis, PRUnichar * teleporterPassword);
+
+ nsresult (*GetFaultToleranceState)(IMachine *pThis, PRUint32 *faultToleranceState);
+ nsresult (*SetFaultToleranceState)(IMachine *pThis, PRUint32 faultToleranceState);
+
+ nsresult (*GetFaultTolerancePort)(IMachine *pThis, PRUint32 *faultTolerancePort);
+ nsresult (*SetFaultTolerancePort)(IMachine *pThis, PRUint32 faultTolerancePort);
+
+ nsresult (*GetFaultToleranceAddress)(IMachine *pThis, PRUnichar * *faultToleranceAddress);
+ nsresult (*SetFaultToleranceAddress)(IMachine *pThis, PRUnichar * faultToleranceAddress);
+
+ nsresult (*GetFaultTolerancePassword)(IMachine *pThis, PRUnichar * *faultTolerancePassword);
+ nsresult (*SetFaultTolerancePassword)(IMachine *pThis, PRUnichar * faultTolerancePassword);
+
+ nsresult (*GetFaultToleranceSyncInterval)(IMachine *pThis, PRUint32 *faultToleranceSyncInterval);
+ nsresult (*SetFaultToleranceSyncInterval)(IMachine *pThis, PRUint32 faultToleranceSyncInterval);
+
+ nsresult (*GetRTCUseUTC)(IMachine *pThis, PRBool *RTCUseUTC);
+ nsresult (*SetRTCUseUTC)(IMachine *pThis, PRBool RTCUseUTC);
+
+ nsresult (*GetIoCacheEnabled)(IMachine *pThis, PRBool *ioCacheEnabled);
+ nsresult (*SetIoCacheEnabled)(IMachine *pThis, PRBool ioCacheEnabled);
+
+ nsresult (*GetIoCacheSize)(IMachine *pThis, PRUint32 *ioCacheSize);
+ nsresult (*SetIoCacheSize)(IMachine *pThis, PRUint32 ioCacheSize);
+
+ nsresult (*GetBandwidthControl)(IMachine *pThis, IBandwidthControl * *bandwidthControl);
+
+ nsresult (*GetPciDeviceAssignments)(IMachine *pThis, PRUint32 *pciDeviceAssignmentsSize, IPciDeviceAttachment * **pciDeviceAssignments);
+
+ nsresult (*LockMachine)(
+ IMachine *pThis,
+ ISession * session,
+ PRUint32 lockType
+ );
+
+ nsresult (*LaunchVMProcess)(
+ IMachine *pThis,
+ ISession * session,
+ PRUnichar * type,
+ PRUnichar * environment,
+ IProgress * * progress
+ );
+
+ nsresult (*SetBootOrder)(
+ IMachine *pThis,
+ PRUint32 position,
+ PRUint32 device
+ );
+
+ nsresult (*GetBootOrder)(
+ IMachine *pThis,
+ PRUint32 position,
+ PRUint32 * device
+ );
+
+ nsresult (*AttachDevice)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device,
+ PRUint32 type,
+ IMedium * medium
+ );
+
+ nsresult (*DetachDevice)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device
+ );
+
+ nsresult (*PassthroughDevice)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device,
+ PRBool passthrough
+ );
+
+ nsresult (*TemporaryEjectDevice)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device,
+ PRBool temporaryEject
+ );
+
+ nsresult (*NonRotationalDevice)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device,
+ PRBool nonRotational
+ );
+
+ nsresult (*SetBandwidthGroupForDevice)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device,
+ IBandwidthGroup * bandwidthGroup
+ );
+
+ nsresult (*MountMedium)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device,
+ IMedium * medium,
+ PRBool force
+ );
+
+ nsresult (*GetMedium)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device,
+ IMedium * * medium
+ );
+
+ nsresult (*GetMediumAttachmentsOfController)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRUint32 *mediumAttachmentsSize,
+ IMediumAttachment *** mediumAttachments
+ );
+
+ nsresult (*GetMediumAttachment)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRInt32 controllerPort,
+ PRInt32 device,
+ IMediumAttachment * * attachment
+ );
+
+ nsresult (*AttachHostPciDevice)(
+ IMachine *pThis,
+ PRInt32 hostAddress,
+ PRInt32 desiredGuestAddress,
+ PRBool tryToUnbind
+ );
+
+ nsresult (*DetachHostPciDevice)(
+ IMachine *pThis,
+ PRInt32 hostAddress
+ );
+
+ nsresult (*GetNetworkAdapter)(
+ IMachine *pThis,
+ PRUint32 slot,
+ INetworkAdapter * * adapter
+ );
+
+ nsresult (*AddStorageController)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRUint32 connectionType,
+ IStorageController * * controller
+ );
+
+ nsresult (*GetStorageControllerByName)(
+ IMachine *pThis,
+ PRUnichar * name,
+ IStorageController * * storageController
+ );
+
+ nsresult (*GetStorageControllerByInstance)(
+ IMachine *pThis,
+ PRUint32 instance,
+ IStorageController * * storageController
+ );
+
+ nsresult (*RemoveStorageController)(
+ IMachine *pThis,
+ PRUnichar * name
+ );
+
+ nsresult (*SetStorageControllerBootable)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRBool bootable
+ );
+
+ nsresult (*GetSerialPort)(
+ IMachine *pThis,
+ PRUint32 slot,
+ ISerialPort * * port
+ );
+
+ nsresult (*GetParallelPort)(
+ IMachine *pThis,
+ PRUint32 slot,
+ IParallelPort * * port
+ );
+
+ nsresult (*GetExtraDataKeys)(
+ IMachine *pThis,
+ PRUint32 *valueSize,
+ PRUnichar *** value
+ );
+
+ nsresult (*GetExtraData)(
+ IMachine *pThis,
+ PRUnichar * key,
+ PRUnichar * * value
+ );
+
+ nsresult (*SetExtraData)(
+ IMachine *pThis,
+ PRUnichar * key,
+ PRUnichar * value
+ );
+
+ nsresult (*GetCPUProperty)(
+ IMachine *pThis,
+ PRUint32 property,
+ PRBool * value
+ );
+
+ nsresult (*SetCPUProperty)(
+ IMachine *pThis,
+ PRUint32 property,
+ PRBool value
+ );
+
+ nsresult (*GetCPUIDLeaf)(
+ IMachine *pThis,
+ PRUint32 id,
+ PRUint32 * valEax,
+ PRUint32 * valEbx,
+ PRUint32 * valEcx,
+ PRUint32 * valEdx
+ );
+
+ nsresult (*SetCPUIDLeaf)(
+ IMachine *pThis,
+ PRUint32 id,
+ PRUint32 valEax,
+ PRUint32 valEbx,
+ PRUint32 valEcx,
+ PRUint32 valEdx
+ );
+
+ nsresult (*RemoveCPUIDLeaf)(
+ IMachine *pThis,
+ PRUint32 id
+ );
+
+ nsresult (*RemoveAllCPUIDLeaves)(IMachine *pThis );
+
+ nsresult (*GetHWVirtExProperty)(
+ IMachine *pThis,
+ PRUint32 property,
+ PRBool * value
+ );
+
+ nsresult (*SetHWVirtExProperty)(
+ IMachine *pThis,
+ PRUint32 property,
+ PRBool value
+ );
+
+ nsresult (*SaveSettings)(IMachine *pThis );
+
+ nsresult (*DiscardSettings)(IMachine *pThis );
+
+ nsresult (*Unregister)(
+ IMachine *pThis,
+ PRUint32 cleanupMode,
+ PRUint32 *aMediaSize,
+ IMedium *** aMedia
+ );
+
+ nsresult (*Delete)(
+ IMachine *pThis,
+ PRUint32 aMediaSize,
+ IMedium ** aMedia,
+ IProgress * * aProgress
+ );
+
+ nsresult (*Export)(
+ IMachine *pThis,
+ IAppliance * aAppliance,
+ PRUnichar * location,
+ IVirtualSystemDescription * * aDescription
+ );
+
+ nsresult (*FindSnapshot)(
+ IMachine *pThis,
+ PRUnichar * nameOrId,
+ ISnapshot * * snapshot
+ );
+
+ nsresult (*CreateSharedFolder)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRUnichar * hostPath,
+ PRBool writable,
+ PRBool automount
+ );
+
+ nsresult (*RemoveSharedFolder)(
+ IMachine *pThis,
+ PRUnichar * name
+ );
+
+ nsresult (*CanShowConsoleWindow)(
+ IMachine *pThis,
+ PRBool * canShow
+ );
+
+ nsresult (*ShowConsoleWindow)(
+ IMachine *pThis,
+ PRInt64 * winId
+ );
+
+ nsresult (*GetGuestProperty)(
+ IMachine *pThis,
+ PRUnichar * name,
+ PRUnichar * * value,
+ PRInt64 * timestamp,
+ PRUnichar * * flags
+ );
+
+ nsresult (*GetGuestPropertyValue)(
+ IMachine *pThis,
+ PRUnichar * property,
+ PRUnichar * * value
+ );
+
+ nsresult (*GetGuestPropertyTimestamp)(
+ IMachine *pThis,
+ PRUnichar * property,
+ PRInt64 * value
+ );
+
+ nsresult (*SetGuestProperty)(
+ IMachine *pThis,
+ PRUnichar * property,
+ PRUnichar * value,
+ PRUnichar * flags
+ );
+
+ nsresult (*SetGuestPropertyValue)(
+ IMachine *pThis,
+ PRUnichar * property,
+ PRUnichar * value
+ );
+
+ nsresult (*EnumerateGuestProperties)(
+ IMachine *pThis,
+ PRUnichar * patterns,
+ PRUint32 *nameSize,
+ PRUnichar *** name,
+ PRUint32 *valueSize,
+ PRUnichar *** value,
+ PRUint32 *timestampSize,
+ PRInt64* timestamp,
+ PRUint32 *flagsSize,
+ PRUnichar *** flags
+ );
+
+ nsresult (*QuerySavedGuestSize)(
+ IMachine *pThis,
+ PRUint32 screenId,
+ PRUint32 * width,
+ PRUint32 * height
+ );
+
+ nsresult (*QuerySavedThumbnailSize)(
+ IMachine *pThis,
+ PRUint32 screenId,
+ PRUint32 * size,
+ PRUint32 * width,
+ PRUint32 * height
+ );
+
+ nsresult (*ReadSavedThumbnailToArray)(
+ IMachine *pThis,
+ PRUint32 screenId,
+ PRBool BGR,
+ PRUint32 * width,
+ PRUint32 * height,
+ PRUint32 *dataSize,
+ PRUint8** data
+ );
+
+ nsresult (*ReadSavedThumbnailPNGToArray)(
+ IMachine *pThis,
+ PRUint32 screenId,
+ PRUint32 * width,
+ PRUint32 * height,
+ PRUint32 *dataSize,
+ PRUint8** data
+ );
+
+ nsresult (*QuerySavedScreenshotPNGSize)(
+ IMachine *pThis,
+ PRUint32 screenId,
+ PRUint32 * size,
+ PRUint32 * width,
+ PRUint32 * height
+ );
+
+ nsresult (*ReadSavedScreenshotPNGToArray)(
+ IMachine *pThis,
+ PRUint32 screenId,
+ PRUint32 * width,
+ PRUint32 * height,
+ PRUint32 *dataSize,
+ PRUint8** data
+ );
+
+ nsresult (*HotPlugCPU)(
+ IMachine *pThis,
+ PRUint32 cpu
+ );
+
+ nsresult (*HotUnplugCPU)(
+ IMachine *pThis,
+ PRUint32 cpu
+ );
+
+ nsresult (*GetCPUStatus)(
+ IMachine *pThis,
+ PRUint32 cpu,
+ PRBool * attached
+ );
+
+ nsresult (*QueryLogFilename)(
+ IMachine *pThis,
+ PRUint32 idx,
+ PRUnichar * * filename
+ );
+
+ nsresult (*ReadLog)(
+ IMachine *pThis,
+ PRUint32 idx,
+ PRInt64 offset,
+ PRInt64 size,
+ PRUint32 *dataSize,
+ PRUint8** data
+ );
+
+ nsresult (*CloneTo)(
+ IMachine *pThis,
+ IMachine * target,
+ PRUint32 mode,
+ PRUint32 optionsSize,
+ PRUint32* options,
+ IProgress * * progress
+ );
+
+};
+
+struct IMachine
+{
+ struct IMachine_vtbl *vtbl;
+};
+/* End of struct IMachine Declaration */
+
+
+/* Start of struct IVRDEServerInfo Declaration */
+#define IVRDESERVERINFO_IID_STR "714434a1-58c3-4aab-9049-7652c5df113b"
+#define IVRDESERVERINFO_IID { \
+ 0x714434a1, 0x58c3, 0x4aab, \
+ { 0x90, 0x49, 0x76, 0x52, 0xc5, 0xdf, 0x11, 0x3b } \
+}
+struct IVRDEServerInfo_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetActive)(IVRDEServerInfo *pThis, PRBool *active);
+
+ nsresult (*GetPort)(IVRDEServerInfo *pThis, PRInt32 *port);
+
+ nsresult (*GetNumberOfClients)(IVRDEServerInfo *pThis, PRUint32 *numberOfClients);
+
+ nsresult (*GetBeginTime)(IVRDEServerInfo *pThis, PRInt64 *beginTime);
+
+ nsresult (*GetEndTime)(IVRDEServerInfo *pThis, PRInt64 *endTime);
+
+ nsresult (*GetBytesSent)(IVRDEServerInfo *pThis, PRInt64 *bytesSent);
+
+ nsresult (*GetBytesSentTotal)(IVRDEServerInfo *pThis, PRInt64 *bytesSentTotal);
+
+ nsresult (*GetBytesReceived)(IVRDEServerInfo *pThis, PRInt64 *bytesReceived);
+
+ nsresult (*GetBytesReceivedTotal)(IVRDEServerInfo *pThis, PRInt64 *bytesReceivedTotal);
+
+ nsresult (*GetUser)(IVRDEServerInfo *pThis, PRUnichar * *user);
+
+ nsresult (*GetDomain)(IVRDEServerInfo *pThis, PRUnichar * *domain);
+
+ nsresult (*GetClientName)(IVRDEServerInfo *pThis, PRUnichar * *clientName);
+
+ nsresult (*GetClientIP)(IVRDEServerInfo *pThis, PRUnichar * *clientIP);
+
+ nsresult (*GetClientVersion)(IVRDEServerInfo *pThis, PRUint32 *clientVersion);
+
+ nsresult (*GetEncryptionStyle)(IVRDEServerInfo *pThis, PRUint32 *encryptionStyle);
+
+};
+
+struct IVRDEServerInfo
+{
+ struct IVRDEServerInfo_vtbl *vtbl;
+};
+/* End of struct IVRDEServerInfo Declaration */
+
+
+/* Start of struct IConsole Declaration */
+#define ICONSOLE_IID_STR "1968b7d3-e3bf-4ceb-99e0-cb7c913317bb"
+#define ICONSOLE_IID { \
+ 0x1968b7d3, 0xe3bf, 0x4ceb, \
+ { 0x99, 0xe0, 0xcb, 0x7c, 0x91, 0x33, 0x17, 0xbb } \
+}
+struct IConsole_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetMachine)(IConsole *pThis, IMachine * *machine);
+
+ nsresult (*GetState)(IConsole *pThis, PRUint32 *state);
+
+ nsresult (*GetGuest)(IConsole *pThis, IGuest * *guest);
+
+ nsresult (*GetKeyboard)(IConsole *pThis, IKeyboard * *keyboard);
+
+ nsresult (*GetMouse)(IConsole *pThis, IMouse * *mouse);
+
+ nsresult (*GetDisplay)(IConsole *pThis, IDisplay * *display);
+
+ nsresult (*GetDebugger)(IConsole *pThis, IMachineDebugger * *debugger);
+
+ nsresult (*GetUSBDevices)(IConsole *pThis, PRUint32 *USBDevicesSize, IUSBDevice * **USBDevices);
+
+ nsresult (*GetRemoteUSBDevices)(IConsole *pThis, PRUint32 *remoteUSBDevicesSize, IHostUSBDevice * **remoteUSBDevices);
+
+ nsresult (*GetSharedFolders)(IConsole *pThis, PRUint32 *sharedFoldersSize, ISharedFolder * **sharedFolders);
+
+ nsresult (*GetVRDEServerInfo)(IConsole *pThis, IVRDEServerInfo * *VRDEServerInfo);
+
+ nsresult (*GetEventSource)(IConsole *pThis, IEventSource * *eventSource);
+
+ nsresult (*GetAttachedPciDevices)(IConsole *pThis, PRUint32 *attachedPciDevicesSize, IPciDeviceAttachment * **attachedPciDevices);
+
+ nsresult (*GetUseHostClipboard)(IConsole *pThis, PRBool *useHostClipboard);
+ nsresult (*SetUseHostClipboard)(IConsole *pThis, PRBool useHostClipboard);
+
+ nsresult (*PowerUp)(
+ IConsole *pThis,
+ IProgress * * progress
+ );
+
+ nsresult (*PowerUpPaused)(
+ IConsole *pThis,
+ IProgress * * progress
+ );
+
+ nsresult (*PowerDown)(
+ IConsole *pThis,
+ IProgress * * progress
+ );
+
+ nsresult (*Reset)(IConsole *pThis );
+
+ nsresult (*Pause)(IConsole *pThis );
+
+ nsresult (*Resume)(IConsole *pThis );
+
+ nsresult (*PowerButton)(IConsole *pThis );
+
+ nsresult (*SleepButton)(IConsole *pThis );
+
+ nsresult (*GetPowerButtonHandled)(
+ IConsole *pThis,
+ PRBool * handled
+ );
+
+ nsresult (*GetGuestEnteredACPIMode)(
+ IConsole *pThis,
+ PRBool * entered
+ );
+
+ nsresult (*SaveState)(
+ IConsole *pThis,
+ IProgress * * progress
+ );
+
+ nsresult (*AdoptSavedState)(
+ IConsole *pThis,
+ PRUnichar * savedStateFile
+ );
+
+ nsresult (*DiscardSavedState)(
+ IConsole *pThis,
+ PRBool fRemoveFile
+ );
+
+ nsresult (*GetDeviceActivity)(
+ IConsole *pThis,
+ PRUint32 type,
+ PRUint32 * activity
+ );
+
+ nsresult (*AttachUSBDevice)(
+ IConsole *pThis,
+ PRUnichar * id
+ );
+
+ nsresult (*DetachUSBDevice)(
+ IConsole *pThis,
+ PRUnichar * id,
+ IUSBDevice * * device
+ );
+
+ nsresult (*FindUSBDeviceByAddress)(
+ IConsole *pThis,
+ PRUnichar * name,
+ IUSBDevice * * device
+ );
+
+ nsresult (*FindUSBDeviceById)(
+ IConsole *pThis,
+ PRUnichar * id,
+ IUSBDevice * * device
+ );
+
+ nsresult (*CreateSharedFolder)(
+ IConsole *pThis,
+ PRUnichar * name,
+ PRUnichar * hostPath,
+ PRBool writable,
+ PRBool automount
+ );
+
+ nsresult (*RemoveSharedFolder)(
+ IConsole *pThis,
+ PRUnichar * name
+ );
+
+ nsresult (*TakeSnapshot)(
+ IConsole *pThis,
+ PRUnichar * name,
+ PRUnichar * description,
+ IProgress * * progress
+ );
+
+ nsresult (*DeleteSnapshot)(
+ IConsole *pThis,
+ PRUnichar * id,
+ IProgress * * progress
+ );
+
+ nsresult (*DeleteSnapshotAndAllChildren)(
+ IConsole *pThis,
+ PRUnichar * id,
+ IProgress * * progress
+ );
+
+ nsresult (*DeleteSnapshotRange)(
+ IConsole *pThis,
+ PRUnichar * startId,
+ PRUnichar * endId,
+ IProgress * * progress
+ );
+
+ nsresult (*RestoreSnapshot)(
+ IConsole *pThis,
+ ISnapshot * snapshot,
+ IProgress * * progress
+ );
+
+ nsresult (*Teleport)(
+ IConsole *pThis,
+ PRUnichar * hostname,
+ PRUint32 tcpport,
+ PRUnichar * password,
+ PRUint32 maxDowntime,
+ IProgress * * progress
+ );
+
+};
+
+struct IConsole
+{
+ struct IConsole_vtbl *vtbl;
+};
+/* End of struct IConsole Declaration */
+
+
+/* Start of struct IHostNetworkInterface Declaration */
+#define IHOSTNETWORKINTERFACE_IID_STR "ce6fae58-7642-4102-b5db-c9005c2320a8"
+#define IHOSTNETWORKINTERFACE_IID { \
+ 0xce6fae58, 0x7642, 0x4102, \
+ { 0xb5, 0xdb, 0xc9, 0x00, 0x5c, 0x23, 0x20, 0xa8 } \
+}
+struct IHostNetworkInterface_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetName)(IHostNetworkInterface *pThis, PRUnichar * *name);
+
+ nsresult (*GetId)(IHostNetworkInterface *pThis, PRUnichar * *id);
+
+ nsresult (*GetNetworkName)(IHostNetworkInterface *pThis, PRUnichar * *networkName);
+
+ nsresult (*GetDhcpEnabled)(IHostNetworkInterface *pThis, PRBool *dhcpEnabled);
+
+ nsresult (*GetIPAddress)(IHostNetworkInterface *pThis, PRUnichar * *IPAddress);
+
+ nsresult (*GetNetworkMask)(IHostNetworkInterface *pThis, PRUnichar * *networkMask);
+
+ nsresult (*GetIPV6Supported)(IHostNetworkInterface *pThis, PRBool *IPV6Supported);
+
+ nsresult (*GetIPV6Address)(IHostNetworkInterface *pThis, PRUnichar * *IPV6Address);
+
+ nsresult (*GetIPV6NetworkMaskPrefixLength)(IHostNetworkInterface *pThis, PRUint32 *IPV6NetworkMaskPrefixLength);
+
+ nsresult (*GetHardwareAddress)(IHostNetworkInterface *pThis, PRUnichar * *hardwareAddress);
+
+ nsresult (*GetMediumType)(IHostNetworkInterface *pThis, PRUint32 *mediumType);
+
+ nsresult (*GetStatus)(IHostNetworkInterface *pThis, PRUint32 *status);
+
+ nsresult (*GetInterfaceType)(IHostNetworkInterface *pThis, PRUint32 *interfaceType);
+
+ nsresult (*EnableStaticIpConfig)(
+ IHostNetworkInterface *pThis,
+ PRUnichar * IPAddress,
+ PRUnichar * networkMask
+ );
+
+ nsresult (*EnableStaticIpConfigV6)(
+ IHostNetworkInterface *pThis,
+ PRUnichar * IPV6Address,
+ PRUint32 IPV6NetworkMaskPrefixLength
+ );
+
+ nsresult (*EnableDynamicIpConfig)(IHostNetworkInterface *pThis );
+
+ nsresult (*DhcpRediscover)(IHostNetworkInterface *pThis );
+
+};
+
+struct IHostNetworkInterface
+{
+ struct IHostNetworkInterface_vtbl *vtbl;
+};
+/* End of struct IHostNetworkInterface Declaration */
+
+
+/* Start of struct IHost Declaration */
+#define IHOST_IID_STR "dab4a2b8-c735-4f08-94fc-9bec84182e2f"
+#define IHOST_IID { \
+ 0xdab4a2b8, 0xc735, 0x4f08, \
+ { 0x94, 0xfc, 0x9b, 0xec, 0x84, 0x18, 0x2e, 0x2f } \
+}
+struct IHost_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetDVDDrives)(IHost *pThis, PRUint32 *DVDDrivesSize, IMedium * **DVDDrives);
+
+ nsresult (*GetFloppyDrives)(IHost *pThis, PRUint32 *floppyDrivesSize, IMedium * **floppyDrives);
+
+ nsresult (*GetUSBDevices)(IHost *pThis, PRUint32 *USBDevicesSize, IHostUSBDevice * **USBDevices);
+
+ nsresult (*GetUSBDeviceFilters)(IHost *pThis, PRUint32 *USBDeviceFiltersSize, IHostUSBDeviceFilter * **USBDeviceFilters);
+
+ nsresult (*GetNetworkInterfaces)(IHost *pThis, PRUint32 *networkInterfacesSize, IHostNetworkInterface * **networkInterfaces);
+
+ nsresult (*GetProcessorCount)(IHost *pThis, PRUint32 *processorCount);
+
+ nsresult (*GetProcessorOnlineCount)(IHost *pThis, PRUint32 *processorOnlineCount);
+
+ nsresult (*GetProcessorCoreCount)(IHost *pThis, PRUint32 *processorCoreCount);
+
+ nsresult (*GetMemorySize)(IHost *pThis, PRUint32 *memorySize);
+
+ nsresult (*GetMemoryAvailable)(IHost *pThis, PRUint32 *memoryAvailable);
+
+ nsresult (*GetOperatingSystem)(IHost *pThis, PRUnichar * *operatingSystem);
+
+ nsresult (*GetOSVersion)(IHost *pThis, PRUnichar * *OSVersion);
+
+ nsresult (*GetUTCTime)(IHost *pThis, PRInt64 *UTCTime);
+
+ nsresult (*GetAcceleration3DAvailable)(IHost *pThis, PRBool *Acceleration3DAvailable);
+
+ nsresult (*GetProcessorSpeed)(
+ IHost *pThis,
+ PRUint32 cpuId,
+ PRUint32 * speed
+ );
+
+ nsresult (*GetProcessorFeature)(
+ IHost *pThis,
+ PRUint32 feature,
+ PRBool * supported
+ );
+
+ nsresult (*GetProcessorDescription)(
+ IHost *pThis,
+ PRUint32 cpuId,
+ PRUnichar * * description
+ );
+
+ nsresult (*GetProcessorCPUIDLeaf)(
+ IHost *pThis,
+ PRUint32 cpuId,
+ PRUint32 leaf,
+ PRUint32 subLeaf,
+ PRUint32 * valEax,
+ PRUint32 * valEbx,
+ PRUint32 * valEcx,
+ PRUint32 * valEdx
+ );
+
+ nsresult (*CreateHostOnlyNetworkInterface)(
+ IHost *pThis,
+ IHostNetworkInterface * * hostInterface,
+ IProgress * * progress
+ );
+
+ nsresult (*RemoveHostOnlyNetworkInterface)(
+ IHost *pThis,
+ PRUnichar * id,
+ IProgress * * progress
+ );
+
+ nsresult (*CreateUSBDeviceFilter)(
+ IHost *pThis,
+ PRUnichar * name,
+ IHostUSBDeviceFilter * * filter
+ );
+
+ nsresult (*InsertUSBDeviceFilter)(
+ IHost *pThis,
+ PRUint32 position,
+ IHostUSBDeviceFilter * filter
+ );
+
+ nsresult (*RemoveUSBDeviceFilter)(
+ IHost *pThis,
+ PRUint32 position
+ );
+
+ nsresult (*FindHostDVDDrive)(
+ IHost *pThis,
+ PRUnichar * name,
+ IMedium * * drive
+ );
+
+ nsresult (*FindHostFloppyDrive)(
+ IHost *pThis,
+ PRUnichar * name,
+ IMedium * * drive
+ );
+
+ nsresult (*FindHostNetworkInterfaceByName)(
+ IHost *pThis,
+ PRUnichar * name,
+ IHostNetworkInterface * * networkInterface
+ );
+
+ nsresult (*FindHostNetworkInterfaceById)(
+ IHost *pThis,
+ PRUnichar * id,
+ IHostNetworkInterface * * networkInterface
+ );
+
+ nsresult (*FindHostNetworkInterfacesOfType)(
+ IHost *pThis,
+ PRUint32 type,
+ PRUint32 *networkInterfacesSize,
+ IHostNetworkInterface *** networkInterfaces
+ );
+
+ nsresult (*FindUSBDeviceById)(
+ IHost *pThis,
+ PRUnichar * id,
+ IHostUSBDevice * * device
+ );
+
+ nsresult (*FindUSBDeviceByAddress)(
+ IHost *pThis,
+ PRUnichar * name,
+ IHostUSBDevice * * device
+ );
+
+ nsresult (*GenerateMACAddress)(
+ IHost *pThis,
+ PRUnichar * * address
+ );
+
+};
+
+struct IHost
+{
+ struct IHost_vtbl *vtbl;
+};
+/* End of struct IHost Declaration */
+
+
+/* Start of struct ISystemProperties Declaration */
+#define ISYSTEMPROPERTIES_IID_STR "8a0ab9ab-48c1-4d04-954b-4a751413d084"
+#define ISYSTEMPROPERTIES_IID { \
+ 0x8a0ab9ab, 0x48c1, 0x4d04, \
+ { 0x95, 0x4b, 0x4a, 0x75, 0x14, 0x13, 0xd0, 0x84 } \
+}
+struct ISystemProperties_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetMinGuestRAM)(ISystemProperties *pThis, PRUint32 *minGuestRAM);
+
+ nsresult (*GetMaxGuestRAM)(ISystemProperties *pThis, PRUint32 *maxGuestRAM);
+
+ nsresult (*GetMinGuestVRAM)(ISystemProperties *pThis, PRUint32 *minGuestVRAM);
+
+ nsresult (*GetMaxGuestVRAM)(ISystemProperties *pThis, PRUint32 *maxGuestVRAM);
+
+ nsresult (*GetMinGuestCPUCount)(ISystemProperties *pThis, PRUint32 *minGuestCPUCount);
+
+ nsresult (*GetMaxGuestCPUCount)(ISystemProperties *pThis, PRUint32 *maxGuestCPUCount);
+
+ nsresult (*GetMaxGuestMonitors)(ISystemProperties *pThis, PRUint32 *maxGuestMonitors);
+
+ nsresult (*GetInfoVDSize)(ISystemProperties *pThis, PRInt64 *infoVDSize);
+
+ nsresult (*GetSerialPortCount)(ISystemProperties *pThis, PRUint32 *serialPortCount);
+
+ nsresult (*GetParallelPortCount)(ISystemProperties *pThis, PRUint32 *parallelPortCount);
+
+ nsresult (*GetMaxBootPosition)(ISystemProperties *pThis, PRUint32 *maxBootPosition);
+
+ nsresult (*GetDefaultMachineFolder)(ISystemProperties *pThis, PRUnichar * *defaultMachineFolder);
+ nsresult (*SetDefaultMachineFolder)(ISystemProperties *pThis, PRUnichar * defaultMachineFolder);
+
+ nsresult (*GetMediumFormats)(ISystemProperties *pThis, PRUint32 *mediumFormatsSize, IMediumFormat * **mediumFormats);
+
+ nsresult (*GetDefaultHardDiskFormat)(ISystemProperties *pThis, PRUnichar * *defaultHardDiskFormat);
+ nsresult (*SetDefaultHardDiskFormat)(ISystemProperties *pThis, PRUnichar * defaultHardDiskFormat);
+
+ nsresult (*GetFreeDiskSpaceWarning)(ISystemProperties *pThis, PRInt64 *freeDiskSpaceWarning);
+ nsresult (*SetFreeDiskSpaceWarning)(ISystemProperties *pThis, PRInt64 freeDiskSpaceWarning);
+
+ nsresult (*GetFreeDiskSpacePercentWarning)(ISystemProperties *pThis, PRUint32 *freeDiskSpacePercentWarning);
+ nsresult (*SetFreeDiskSpacePercentWarning)(ISystemProperties *pThis, PRUint32 freeDiskSpacePercentWarning);
+
+ nsresult (*GetFreeDiskSpaceError)(ISystemProperties *pThis, PRInt64 *freeDiskSpaceError);
+ nsresult (*SetFreeDiskSpaceError)(ISystemProperties *pThis, PRInt64 freeDiskSpaceError);
+
+ nsresult (*GetFreeDiskSpacePercentError)(ISystemProperties *pThis, PRUint32 *freeDiskSpacePercentError);
+ nsresult (*SetFreeDiskSpacePercentError)(ISystemProperties *pThis, PRUint32 freeDiskSpacePercentError);
+
+ nsresult (*GetVRDEAuthLibrary)(ISystemProperties *pThis, PRUnichar * *VRDEAuthLibrary);
+ nsresult (*SetVRDEAuthLibrary)(ISystemProperties *pThis, PRUnichar * VRDEAuthLibrary);
+
+ nsresult (*GetWebServiceAuthLibrary)(ISystemProperties *pThis, PRUnichar * *webServiceAuthLibrary);
+ nsresult (*SetWebServiceAuthLibrary)(ISystemProperties *pThis, PRUnichar * webServiceAuthLibrary);
+
+ nsresult (*GetDefaultVRDEExtPack)(ISystemProperties *pThis, PRUnichar * *defaultVRDEExtPack);
+ nsresult (*SetDefaultVRDEExtPack)(ISystemProperties *pThis, PRUnichar * defaultVRDEExtPack);
+
+ nsresult (*GetLogHistoryCount)(ISystemProperties *pThis, PRUint32 *logHistoryCount);
+ nsresult (*SetLogHistoryCount)(ISystemProperties *pThis, PRUint32 logHistoryCount);
+
+ nsresult (*GetDefaultAudioDriver)(ISystemProperties *pThis, PRUint32 *defaultAudioDriver);
+
+ nsresult (*GetMaxNetworkAdapters)(
+ ISystemProperties *pThis,
+ PRUint32 chipset,
+ PRUint32 * maxNetworkAdapters
+ );
+
+ nsresult (*GetMaxNetworkAdaptersOfType)(
+ ISystemProperties *pThis,
+ PRUint32 chipset,
+ PRUint32 type,
+ PRUint32 * maxNetworkAdapters
+ );
+
+ nsresult (*GetMaxDevicesPerPortForStorageBus)(
+ ISystemProperties *pThis,
+ PRUint32 bus,
+ PRUint32 * maxDevicesPerPort
+ );
+
+ nsresult (*GetMinPortCountForStorageBus)(
+ ISystemProperties *pThis,
+ PRUint32 bus,
+ PRUint32 * minPortCount
+ );
+
+ nsresult (*GetMaxPortCountForStorageBus)(
+ ISystemProperties *pThis,
+ PRUint32 bus,
+ PRUint32 * maxPortCount
+ );
+
+ nsresult (*GetMaxInstancesOfStorageBus)(
+ ISystemProperties *pThis,
+ PRUint32 chipset,
+ PRUint32 bus,
+ PRUint32 * maxInstances
+ );
+
+ nsresult (*GetDeviceTypesForStorageBus)(
+ ISystemProperties *pThis,
+ PRUint32 bus,
+ PRUint32 *deviceTypesSize,
+ PRUint32** deviceTypes
+ );
+
+ nsresult (*GetDefaultIoCacheSettingForStorageController)(
+ ISystemProperties *pThis,
+ PRUint32 controllerType,
+ PRBool * enabled
+ );
+
+};
+
+struct ISystemProperties
+{
+ struct ISystemProperties_vtbl *vtbl;
+};
+/* End of struct ISystemProperties Declaration */
+
+
+/* Start of struct IGuestOSType Declaration */
+#define IGUESTOSTYPE_IID_STR "432c1546-1354-4abf-bf08-878a32a373f5"
+#define IGUESTOSTYPE_IID { \
+ 0x432c1546, 0x1354, 0x4abf, \
+ { 0xbf, 0x08, 0x87, 0x8a, 0x32, 0xa3, 0x73, 0xf5 } \
+}
+struct IGuestOSType_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetFamilyId)(IGuestOSType *pThis, PRUnichar * *familyId);
+
+ nsresult (*GetFamilyDescription)(IGuestOSType *pThis, PRUnichar * *familyDescription);
+
+ nsresult (*GetId)(IGuestOSType *pThis, PRUnichar * *id);
+
+ nsresult (*GetDescription)(IGuestOSType *pThis, PRUnichar * *description);
+
+ nsresult (*GetIs64Bit)(IGuestOSType *pThis, PRBool *is64Bit);
+
+ nsresult (*GetRecommendedIOAPIC)(IGuestOSType *pThis, PRBool *recommendedIOAPIC);
+
+ nsresult (*GetRecommendedVirtEx)(IGuestOSType *pThis, PRBool *recommendedVirtEx);
+
+ nsresult (*GetRecommendedRAM)(IGuestOSType *pThis, PRUint32 *recommendedRAM);
+
+ nsresult (*GetRecommendedVRAM)(IGuestOSType *pThis, PRUint32 *recommendedVRAM);
+
+ nsresult (*GetRecommendedHDD)(IGuestOSType *pThis, PRInt64 *recommendedHDD);
+
+ nsresult (*GetAdapterType)(IGuestOSType *pThis, PRUint32 *adapterType);
+
+ nsresult (*GetRecommendedPae)(IGuestOSType *pThis, PRBool *recommendedPae);
+
+ nsresult (*GetRecommendedDvdStorageController)(IGuestOSType *pThis, PRUint32 *recommendedDvdStorageController);
+
+ nsresult (*GetRecommendedDvdStorageBus)(IGuestOSType *pThis, PRUint32 *recommendedDvdStorageBus);
+
+ nsresult (*GetRecommendedHdStorageController)(IGuestOSType *pThis, PRUint32 *recommendedHdStorageController);
+
+ nsresult (*GetRecommendedHdStorageBus)(IGuestOSType *pThis, PRUint32 *recommendedHdStorageBus);
+
+ nsresult (*GetRecommendedFirmware)(IGuestOSType *pThis, PRUint32 *recommendedFirmware);
+
+ nsresult (*GetRecommendedUsbHid)(IGuestOSType *pThis, PRBool *recommendedUsbHid);
+
+ nsresult (*GetRecommendedHpet)(IGuestOSType *pThis, PRBool *recommendedHpet);
+
+ nsresult (*GetRecommendedUsbTablet)(IGuestOSType *pThis, PRBool *recommendedUsbTablet);
+
+ nsresult (*GetRecommendedRtcUseUtc)(IGuestOSType *pThis, PRBool *recommendedRtcUseUtc);
+
+ nsresult (*GetRecommendedChipset)(IGuestOSType *pThis, PRUint32 *recommendedChipset);
+
+ nsresult (*GetRecommendedAudioController)(IGuestOSType *pThis, PRUint32 *recommendedAudioController);
+
+};
+
+struct IGuestOSType
+{
+ struct IGuestOSType_vtbl *vtbl;
+};
+/* End of struct IGuestOSType Declaration */
+
+
+/* Start of struct IAdditionsFacility Declaration */
+#define IADDITIONSFACILITY_IID_STR "54992946-6af1-4e49-98ec-58b558b7291e"
+#define IADDITIONSFACILITY_IID { \
+ 0x54992946, 0x6af1, 0x4e49, \
+ { 0x98, 0xec, 0x58, 0xb5, 0x58, 0xb7, 0x29, 0x1e } \
+}
+struct IAdditionsFacility_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetClassType)(IAdditionsFacility *pThis, PRUint32 *classType);
+
+ nsresult (*GetLastUpdated)(IAdditionsFacility *pThis, PRInt64 *lastUpdated);
+
+ nsresult (*GetName)(IAdditionsFacility *pThis, PRUnichar * *name);
+
+ nsresult (*GetStatus)(IAdditionsFacility *pThis, PRUint32 *status);
+
+ nsresult (*GetType)(IAdditionsFacility *pThis, PRUint32 *type);
+
+};
+
+struct IAdditionsFacility
+{
+ struct IAdditionsFacility_vtbl *vtbl;
+};
+/* End of struct IAdditionsFacility Declaration */
+
+
+/* Start of struct IGuestDirEntry Declaration */
+#define IGUESTDIRENTRY_IID_STR "20a66efc-c2f6-4438-826f-38454c04369e"
+#define IGUESTDIRENTRY_IID { \
+ 0x20a66efc, 0xc2f6, 0x4438, \
+ { 0x82, 0x6f, 0x38, 0x45, 0x4c, 0x04, 0x36, 0x9e } \
+}
+struct IGuestDirEntry_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetNodeId)(IGuestDirEntry *pThis, PRInt64 *nodeId);
+
+ nsresult (*GetName)(IGuestDirEntry *pThis, PRUnichar * *name);
+
+ nsresult (*GetType)(IGuestDirEntry *pThis, PRUint32 *type);
+
+};
+
+struct IGuestDirEntry
+{
+ struct IGuestDirEntry_vtbl *vtbl;
+};
+/* End of struct IGuestDirEntry Declaration */
+
+
+/* Start of struct IGuest Declaration */
+#define IGUEST_IID_STR "ed109b6e-0578-4b17-8ace-52646789f1a0"
+#define IGUEST_IID { \
+ 0xed109b6e, 0x0578, 0x4b17, \
+ { 0x8a, 0xce, 0x52, 0x64, 0x67, 0x89, 0xf1, 0xa0 } \
+}
+struct IGuest_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetOSTypeId)(IGuest *pThis, PRUnichar * *OSTypeId);
+
+ nsresult (*GetAdditionsRunLevel)(IGuest *pThis, PRUint32 *additionsRunLevel);
+
+ nsresult (*GetAdditionsVersion)(IGuest *pThis, PRUnichar * *additionsVersion);
+
+ nsresult (*GetFacilities)(IGuest *pThis, PRUint32 *facilitiesSize, IAdditionsFacility * **facilities);
+
+ nsresult (*GetMemoryBalloonSize)(IGuest *pThis, PRUint32 *memoryBalloonSize);
+ nsresult (*SetMemoryBalloonSize)(IGuest *pThis, PRUint32 memoryBalloonSize);
+
+ nsresult (*GetStatisticsUpdateInterval)(IGuest *pThis, PRUint32 *statisticsUpdateInterval);
+ nsresult (*SetStatisticsUpdateInterval)(IGuest *pThis, PRUint32 statisticsUpdateInterval);
+
+ nsresult (*InternalGetStatistics)(
+ IGuest *pThis,
+ PRUint32 * cpuUser,
+ PRUint32 * cpuKernel,
+ PRUint32 * cpuIdle,
+ PRUint32 * memTotal,
+ PRUint32 * memFree,
+ PRUint32 * memBalloon,
+ PRUint32 * memShared,
+ PRUint32 * memCache,
+ PRUint32 * pagedTotal,
+ PRUint32 * memAllocTotal,
+ PRUint32 * memFreeTotal,
+ PRUint32 * memBalloonTotal,
+ PRUint32 * memSharedTotal
+ );
+
+ nsresult (*GetFacilityStatus)(
+ IGuest *pThis,
+ PRUint32 facility,
+ PRInt64 * timestamp,
+ PRUint32 * status
+ );
+
+ nsresult (*GetAdditionsStatus)(
+ IGuest *pThis,
+ PRUint32 level,
+ PRBool * active
+ );
+
+ nsresult (*SetCredentials)(
+ IGuest *pThis,
+ PRUnichar * userName,
+ PRUnichar * password,
+ PRUnichar * domain,
+ PRBool allowInteractiveLogon
+ );
+
+ nsresult (*ExecuteProcess)(
+ IGuest *pThis,
+ PRUnichar * execName,
+ PRUint32 flags,
+ PRUint32 argumentsSize,
+ PRUnichar ** arguments,
+ PRUint32 environmentSize,
+ PRUnichar ** environment,
+ PRUnichar * userName,
+ PRUnichar * password,
+ PRUint32 timeoutMS,
+ PRUint32 * pid,
+ IProgress * * progress
+ );
+
+ nsresult (*GetProcessOutput)(
+ IGuest *pThis,
+ PRUint32 pid,
+ PRUint32 flags,
+ PRUint32 timeoutMS,
+ PRInt64 size,
+ PRUint32 *dataSize,
+ PRUint8** data
+ );
+
+ nsresult (*GetProcessStatus)(
+ IGuest *pThis,
+ PRUint32 pid,
+ PRUint32 * exitcode,
+ PRUint32 * flags,
+ PRUint32 * reason
+ );
+
+ nsresult (*CopyFromGuest)(
+ IGuest *pThis,
+ PRUnichar * source,
+ PRUnichar * dest,
+ PRUnichar * userName,
+ PRUnichar * password,
+ PRUint32 flags,
+ IProgress * * progress
+ );
+
+ nsresult (*CopyToGuest)(
+ IGuest *pThis,
+ PRUnichar * source,
+ PRUnichar * dest,
+ PRUnichar * userName,
+ PRUnichar * password,
+ PRUint32 flags,
+ IProgress * * progress
+ );
+
+ nsresult (*DirectoryClose)(
+ IGuest *pThis,
+ PRUint32 handle
+ );
+
+ nsresult (*DirectoryCreate)(
+ IGuest *pThis,
+ PRUnichar * directory,
+ PRUnichar * userName,
+ PRUnichar * password,
+ PRUint32 mode,
+ PRUint32 flags
+ );
+
+ nsresult (*DirectoryOpen)(
+ IGuest *pThis,
+ PRUnichar * directory,
+ PRUnichar * filter,
+ PRUint32 flags,
+ PRUnichar * userName,
+ PRUnichar * password,
+ PRUint32 * handle
+ );
+
+ nsresult (*DirectoryRead)(
+ IGuest *pThis,
+ PRUint32 handle,
+ IGuestDirEntry * * entry
+ );
+
+ nsresult (*FileExists)(
+ IGuest *pThis,
+ PRUnichar * file,
+ PRUnichar * userName,
+ PRUnichar * password,
+ PRBool * exists
+ );
+
+ nsresult (*FileQuerySize)(
+ IGuest *pThis,
+ PRUnichar * file,
+ PRUnichar * userName,
+ PRUnichar * password,
+ PRInt64 * size
+ );
+
+ nsresult (*SetProcessInput)(
+ IGuest *pThis,
+ PRUint32 pid,
+ PRUint32 flags,
+ PRUint32 timeoutMS,
+ PRUint32 dataSize,
+ PRUint8* data,
+ PRUint32 * written
+ );
+
+ nsresult (*UpdateGuestAdditions)(
+ IGuest *pThis,
+ PRUnichar * source,
+ PRUint32 flags,
+ IProgress * * progress
+ );
+
+};
+
+struct IGuest
+{
+ struct IGuest_vtbl *vtbl;
+};
+/* End of struct IGuest Declaration */
+
+
+/* Start of struct IProgress Declaration */
+#define IPROGRESS_IID_STR "c20238e4-3221-4d3f-8891-81ce92d9f913"
+#define IPROGRESS_IID { \
+ 0xc20238e4, 0x3221, 0x4d3f, \
+ { 0x88, 0x91, 0x81, 0xce, 0x92, 0xd9, 0xf9, 0x13 } \
+}
+struct IProgress_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetId)(IProgress *pThis, PRUnichar * *id);
+
+ nsresult (*GetDescription)(IProgress *pThis, PRUnichar * *description);
+
+ nsresult (*GetInitiator)(IProgress *pThis, nsISupports * *initiator);
+
+ nsresult (*GetCancelable)(IProgress *pThis, PRBool *cancelable);
+
+ nsresult (*GetPercent)(IProgress *pThis, PRUint32 *percent);
+
+ nsresult (*GetTimeRemaining)(IProgress *pThis, PRInt32 *timeRemaining);
+
+ nsresult (*GetCompleted)(IProgress *pThis, PRBool *completed);
+
+ nsresult (*GetCanceled)(IProgress *pThis, PRBool *canceled);
+
+ nsresult (*GetResultCode)(IProgress *pThis, PRInt32 *resultCode);
+
+ nsresult (*GetErrorInfo)(IProgress *pThis, IVirtualBoxErrorInfo * *errorInfo);
+
+ nsresult (*GetOperationCount)(IProgress *pThis, PRUint32 *operationCount);
+
+ nsresult (*GetOperation)(IProgress *pThis, PRUint32 *operation);
+
+ nsresult (*GetOperationDescription)(IProgress *pThis, PRUnichar * *operationDescription);
+
+ nsresult (*GetOperationPercent)(IProgress *pThis, PRUint32 *operationPercent);
+
+ nsresult (*GetOperationWeight)(IProgress *pThis, PRUint32 *operationWeight);
+
+ nsresult (*GetTimeout)(IProgress *pThis, PRUint32 *timeout);
+ nsresult (*SetTimeout)(IProgress *pThis, PRUint32 timeout);
+
+ nsresult (*SetCurrentOperationProgress)(
+ IProgress *pThis,
+ PRUint32 percent
+ );
+
+ nsresult (*SetNextOperation)(
+ IProgress *pThis,
+ PRUnichar * nextOperationDescription,
+ PRUint32 nextOperationsWeight
+ );
+
+ nsresult (*WaitForCompletion)(
+ IProgress *pThis,
+ PRInt32 timeout
+ );
+
+ nsresult (*WaitForOperationCompletion)(
+ IProgress *pThis,
+ PRUint32 operation,
+ PRInt32 timeout
+ );
+
+ nsresult (*WaitForAsyncProgressCompletion)(
+ IProgress *pThis,
+ IProgress * pProgressAsync
+ );
+
+ nsresult (*Cancel)(IProgress *pThis );
+
+};
+
+struct IProgress
+{
+ struct IProgress_vtbl *vtbl;
+};
+/* End of struct IProgress Declaration */
+
+
+/* Start of struct ISnapshot Declaration */
+#define ISNAPSHOT_IID_STR "0472823b-c6e7-472a-8e9f-d732e86b8463"
+#define ISNAPSHOT_IID { \
+ 0x0472823b, 0xc6e7, 0x472a, \
+ { 0x8e, 0x9f, 0xd7, 0x32, 0xe8, 0x6b, 0x84, 0x63 } \
+}
+struct ISnapshot_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetId)(ISnapshot *pThis, PRUnichar * *id);
+
+ nsresult (*GetName)(ISnapshot *pThis, PRUnichar * *name);
+ nsresult (*SetName)(ISnapshot *pThis, PRUnichar * name);
+
+ nsresult (*GetDescription)(ISnapshot *pThis, PRUnichar * *description);
+ nsresult (*SetDescription)(ISnapshot *pThis, PRUnichar * description);
+
+ nsresult (*GetTimeStamp)(ISnapshot *pThis, PRInt64 *timeStamp);
+
+ nsresult (*GetOnline)(ISnapshot *pThis, PRBool *online);
+
+ nsresult (*GetMachine)(ISnapshot *pThis, IMachine * *machine);
+
+ nsresult (*GetParent)(ISnapshot *pThis, ISnapshot * *parent);
+
+ nsresult (*GetChildren)(ISnapshot *pThis, PRUint32 *childrenSize, ISnapshot * **children);
+
+ nsresult (*GetChildrenCount)(
+ ISnapshot *pThis,
+ PRUint32 * childrenCount
+ );
+
+};
+
+struct ISnapshot
+{
+ struct ISnapshot_vtbl *vtbl;
+};
+/* End of struct ISnapshot Declaration */
+
+
+/* Start of struct IMediumAttachment Declaration */
+#define IMEDIUMATTACHMENT_IID_STR "b5dfbb8c-7498-48c3-bf10-78fc60f064e1"
+#define IMEDIUMATTACHMENT_IID { \
+ 0xb5dfbb8c, 0x7498, 0x48c3, \
+ { 0xbf, 0x10, 0x78, 0xfc, 0x60, 0xf0, 0x64, 0xe1 } \
+}
+struct IMediumAttachment_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetMedium)(IMediumAttachment *pThis, IMedium * *medium);
+
+ nsresult (*GetController)(IMediumAttachment *pThis, PRUnichar * *controller);
+
+ nsresult (*GetPort)(IMediumAttachment *pThis, PRInt32 *port);
+
+ nsresult (*GetDevice)(IMediumAttachment *pThis, PRInt32 *device);
+
+ nsresult (*GetType)(IMediumAttachment *pThis, PRUint32 *type);
+
+ nsresult (*GetPassthrough)(IMediumAttachment *pThis, PRBool *passthrough);
+
+ nsresult (*GetTemporaryEject)(IMediumAttachment *pThis, PRBool *temporaryEject);
+
+ nsresult (*GetIsEjected)(IMediumAttachment *pThis, PRBool *isEjected);
+
+ nsresult (*GetNonRotational)(IMediumAttachment *pThis, PRBool *nonRotational);
+
+ nsresult (*GetBandwidthGroup)(IMediumAttachment *pThis, IBandwidthGroup * *bandwidthGroup);
+
+};
+
+struct IMediumAttachment
+{
+ struct IMediumAttachment_vtbl *vtbl;
+};
+/* End of struct IMediumAttachment Declaration */
+
+
+/* Start of struct IMedium Declaration */
+#define IMEDIUM_IID_STR "53f9cc0c-e0fd-40a5-a404-a7a5272082cd"
+#define IMEDIUM_IID { \
+ 0x53f9cc0c, 0xe0fd, 0x40a5, \
+ { 0xa4, 0x04, 0xa7, 0xa5, 0x27, 0x20, 0x82, 0xcd } \
+}
+struct IMedium_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetId)(IMedium *pThis, PRUnichar * *id);
+
+ nsresult (*GetDescription)(IMedium *pThis, PRUnichar * *description);
+ nsresult (*SetDescription)(IMedium *pThis, PRUnichar * description);
+
+ nsresult (*GetState)(IMedium *pThis, PRUint32 *state);
+
+ nsresult (*GetVariant)(IMedium *pThis, PRUint32 *variant);
+
+ nsresult (*GetLocation)(IMedium *pThis, PRUnichar * *location);
+ nsresult (*SetLocation)(IMedium *pThis, PRUnichar * location);
+
+ nsresult (*GetName)(IMedium *pThis, PRUnichar * *name);
+
+ nsresult (*GetDeviceType)(IMedium *pThis, PRUint32 *deviceType);
+
+ nsresult (*GetHostDrive)(IMedium *pThis, PRBool *hostDrive);
+
+ nsresult (*GetSize)(IMedium *pThis, PRInt64 *size);
+
+ nsresult (*GetFormat)(IMedium *pThis, PRUnichar * *format);
+
+ nsresult (*GetMediumFormat)(IMedium *pThis, IMediumFormat * *mediumFormat);
+
+ nsresult (*GetType)(IMedium *pThis, PRUint32 *type);
+ nsresult (*SetType)(IMedium *pThis, PRUint32 type);
+
+ nsresult (*GetAllowedTypes)(IMedium *pThis, PRUint32 *allowedTypesSize, PRUint32 **allowedTypes);
+
+ nsresult (*GetParent)(IMedium *pThis, IMedium * *parent);
+
+ nsresult (*GetChildren)(IMedium *pThis, PRUint32 *childrenSize, IMedium * **children);
+
+ nsresult (*GetBase)(IMedium *pThis, IMedium * *base);
+
+ nsresult (*GetReadOnly)(IMedium *pThis, PRBool *readOnly);
+
+ nsresult (*GetLogicalSize)(IMedium *pThis, PRInt64 *logicalSize);
+
+ nsresult (*GetAutoReset)(IMedium *pThis, PRBool *autoReset);
+ nsresult (*SetAutoReset)(IMedium *pThis, PRBool autoReset);
+
+ nsresult (*GetLastAccessError)(IMedium *pThis, PRUnichar * *lastAccessError);
+
+ nsresult (*GetMachineIds)(IMedium *pThis, PRUint32 *machineIdsSize, PRUnichar * **machineIds);
+
+ nsresult (*SetIDs)(
+ IMedium *pThis,
+ PRBool setImageId,
+ PRUnichar * imageId,
+ PRBool setParentId,
+ PRUnichar * parentId
+ );
+
+ nsresult (*RefreshState)(
+ IMedium *pThis,
+ PRUint32 * state
+ );
+
+ nsresult (*GetSnapshotIds)(
+ IMedium *pThis,
+ PRUnichar * machineId,
+ PRUint32 *snapshotIdsSize,
+ PRUnichar *** snapshotIds
+ );
+
+ nsresult (*LockRead)(
+ IMedium *pThis,
+ PRUint32 * state
+ );
+
+ nsresult (*UnlockRead)(
+ IMedium *pThis,
+ PRUint32 * state
+ );
+
+ nsresult (*LockWrite)(
+ IMedium *pThis,
+ PRUint32 * state
+ );
+
+ nsresult (*UnlockWrite)(
+ IMedium *pThis,
+ PRUint32 * state
+ );
+
+ nsresult (*Close)(IMedium *pThis );
+
+ nsresult (*GetProperty)(
+ IMedium *pThis,
+ PRUnichar * name,
+ PRUnichar * * value
+ );
+
+ nsresult (*SetProperty)(
+ IMedium *pThis,
+ PRUnichar * name,
+ PRUnichar * value
+ );
+
+ nsresult (*GetProperties)(
+ IMedium *pThis,
+ PRUnichar * names,
+ PRUint32 *returnNamesSize,
+ PRUnichar *** returnNames,
+ PRUint32 *returnValuesSize,
+ PRUnichar *** returnValues
+ );
+
+ nsresult (*SetProperties)(
+ IMedium *pThis,
+ PRUint32 namesSize,
+ PRUnichar ** names,
+ PRUint32 valuesSize,
+ PRUnichar ** values
+ );
+
+ nsresult (*CreateBaseStorage)(
+ IMedium *pThis,
+ PRInt64 logicalSize,
+ PRUint32 variant,
+ IProgress * * progress
+ );
+
+ nsresult (*DeleteStorage)(
+ IMedium *pThis,
+ IProgress * * progress
+ );
+
+ nsresult (*CreateDiffStorage)(
+ IMedium *pThis,
+ IMedium * target,
+ PRUint32 variant,
+ IProgress * * progress
+ );
+
+ nsresult (*MergeTo)(
+ IMedium *pThis,
+ IMedium * target,
+ IProgress * * progress
+ );
+
+ nsresult (*CloneTo)(
+ IMedium *pThis,
+ IMedium * target,
+ PRUint32 variant,
+ IMedium * parent,
+ IProgress * * progress
+ );
+
+ nsresult (*Compact)(
+ IMedium *pThis,
+ IProgress * * progress
+ );
+
+ nsresult (*Resize)(
+ IMedium *pThis,
+ PRInt64 logicalSize,
+ IProgress * * progress
+ );
+
+ nsresult (*Reset)(
+ IMedium *pThis,
+ IProgress * * progress
+ );
+
+};
+
+struct IMedium
+{
+ struct IMedium_vtbl *vtbl;
+};
+/* End of struct IMedium Declaration */
+
+
+/* Start of struct IMediumFormat Declaration */
+#define IMEDIUMFORMAT_IID_STR "9bd5b655-ea47-4637-99f3-aad0948be35b"
+#define IMEDIUMFORMAT_IID { \
+ 0x9bd5b655, 0xea47, 0x4637, \
+ { 0x99, 0xf3, 0xaa, 0xd0, 0x94, 0x8b, 0xe3, 0x5b } \
+}
+struct IMediumFormat_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetId)(IMediumFormat *pThis, PRUnichar * *id);
+
+ nsresult (*GetName)(IMediumFormat *pThis, PRUnichar * *name);
+
+ nsresult (*GetCapabilities)(IMediumFormat *pThis, PRUint32 *capabilities);
+
+ nsresult (*DescribeFileExtensions)(
+ IMediumFormat *pThis,
+ PRUint32 *extensionsSize,
+ PRUnichar *** extensions,
+ PRUint32 *typeSize,
+ PRUint32* type
+ );
+
+ nsresult (*DescribeProperties)(
+ IMediumFormat *pThis,
+ PRUint32 *namesSize,
+ PRUnichar *** names,
+ PRUint32 *descriptionSize,
+ PRUnichar *** description,
+ PRUint32 *typesSize,
+ PRUint32* types,
+ PRUint32 *flagsSize,
+ PRUint32* flags,
+ PRUint32 *defaultsSize,
+ PRUnichar *** defaults
+ );
+
+};
+
+struct IMediumFormat
+{
+ struct IMediumFormat_vtbl *vtbl;
+};
+/* End of struct IMediumFormat Declaration */
+
+
+/* Start of struct IKeyboard Declaration */
+#define IKEYBOARD_IID_STR "f6916ec5-a881-4237-898f-7de58cf88672"
+#define IKEYBOARD_IID { \
+ 0xf6916ec5, 0xa881, 0x4237, \
+ { 0x89, 0x8f, 0x7d, 0xe5, 0x8c, 0xf8, 0x86, 0x72 } \
+}
+struct IKeyboard_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetEventSource)(IKeyboard *pThis, IEventSource * *eventSource);
+
+ nsresult (*PutScancode)(
+ IKeyboard *pThis,
+ PRInt32 scancode
+ );
+
+ nsresult (*PutScancodes)(
+ IKeyboard *pThis,
+ PRUint32 scancodesSize,
+ PRInt32* scancodes,
+ PRUint32 * codesStored
+ );
+
+ nsresult (*PutCAD)(IKeyboard *pThis );
+
+};
+
+struct IKeyboard
+{
+ struct IKeyboard_vtbl *vtbl;
+};
+/* End of struct IKeyboard Declaration */
+
+
+/* Start of struct IMouse Declaration */
+#define IMOUSE_IID_STR "05044a52-7811-4f00-ae3a-0ab7ff707b10"
+#define IMOUSE_IID { \
+ 0x05044a52, 0x7811, 0x4f00, \
+ { 0xae, 0x3a, 0x0a, 0xb7, 0xff, 0x70, 0x7b, 0x10 } \
+}
+struct IMouse_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetAbsoluteSupported)(IMouse *pThis, PRBool *absoluteSupported);
+
+ nsresult (*GetRelativeSupported)(IMouse *pThis, PRBool *relativeSupported);
+
+ nsresult (*GetNeedsHostCursor)(IMouse *pThis, PRBool *needsHostCursor);
+
+ nsresult (*GetEventSource)(IMouse *pThis, IEventSource * *eventSource);
+
+ nsresult (*PutMouseEvent)(
+ IMouse *pThis,
+ PRInt32 dx,
+ PRInt32 dy,
+ PRInt32 dz,
+ PRInt32 dw,
+ PRInt32 buttonState
+ );
+
+ nsresult (*PutMouseEventAbsolute)(
+ IMouse *pThis,
+ PRInt32 x,
+ PRInt32 y,
+ PRInt32 dz,
+ PRInt32 dw,
+ PRInt32 buttonState
+ );
+
+};
+
+struct IMouse
+{
+ struct IMouse_vtbl *vtbl;
+};
+/* End of struct IMouse Declaration */
+
+
+/* Start of struct IFramebuffer Declaration */
+#define IFRAMEBUFFER_IID_STR "b7ed347a-5765-40a0-ae1c-f543eb4ddeaf"
+#define IFRAMEBUFFER_IID { \
+ 0xb7ed347a, 0x5765, 0x40a0, \
+ { 0xae, 0x1c, 0xf5, 0x43, 0xeb, 0x4d, 0xde, 0xaf } \
+}
+struct IFramebuffer_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetAddress)(IFramebuffer *pThis, PRUint8 * *address);
+
+ nsresult (*GetWidth)(IFramebuffer *pThis, PRUint32 *width);
+
+ nsresult (*GetHeight)(IFramebuffer *pThis, PRUint32 *height);
+
+ nsresult (*GetBitsPerPixel)(IFramebuffer *pThis, PRUint32 *bitsPerPixel);
+
+ nsresult (*GetBytesPerLine)(IFramebuffer *pThis, PRUint32 *bytesPerLine);
+
+ nsresult (*GetPixelFormat)(IFramebuffer *pThis, PRUint32 *pixelFormat);
+
+ nsresult (*GetUsesGuestVRAM)(IFramebuffer *pThis, PRBool *usesGuestVRAM);
+
+ nsresult (*GetHeightReduction)(IFramebuffer *pThis, PRUint32 *heightReduction);
+
+ nsresult (*GetOverlay)(IFramebuffer *pThis, IFramebufferOverlay * *overlay);
+
+ nsresult (*GetWinId)(IFramebuffer *pThis, PRInt64 *winId);
+
+ nsresult (*Lock)(IFramebuffer *pThis );
+
+ nsresult (*Unlock)(IFramebuffer *pThis );
+
+ nsresult (*NotifyUpdate)(
+ IFramebuffer *pThis,
+ PRUint32 x,
+ PRUint32 y,
+ PRUint32 width,
+ PRUint32 height
+ );
+
+ nsresult (*RequestResize)(
+ IFramebuffer *pThis,
+ PRUint32 screenId,
+ PRUint32 pixelFormat,
+ PRUint8 * VRAM,
+ PRUint32 bitsPerPixel,
+ PRUint32 bytesPerLine,
+ PRUint32 width,
+ PRUint32 height,
+ PRBool * finished
+ );
+
+ nsresult (*VideoModeSupported)(
+ IFramebuffer *pThis,
+ PRUint32 width,
+ PRUint32 height,
+ PRUint32 bpp,
+ PRBool * supported
+ );
+
+ nsresult (*GetVisibleRegion)(
+ IFramebuffer *pThis,
+ PRUint8 * rectangles,
+ PRUint32 count,
+ PRUint32 * countCopied
+ );
+
+ nsresult (*SetVisibleRegion)(
+ IFramebuffer *pThis,
+ PRUint8 * rectangles,
+ PRUint32 count
+ );
+
+ nsresult (*ProcessVHWACommand)(
+ IFramebuffer *pThis,
+ PRUint8 * command
+ );
+
+};
+
+struct IFramebuffer
+{
+ struct IFramebuffer_vtbl *vtbl;
+};
+/* End of struct IFramebuffer Declaration */
+
+
+/* Start of struct IFramebufferOverlay Declaration */
+#define IFRAMEBUFFEROVERLAY_IID_STR "0bcc1c7e-e415-47d2-bfdb-e4c705fb0f47"
+#define IFRAMEBUFFEROVERLAY_IID { \
+ 0x0bcc1c7e, 0xe415, 0x47d2, \
+ { 0xbf, 0xdb, 0xe4, 0xc7, 0x05, 0xfb, 0x0f, 0x47 } \
+}
+struct IFramebufferOverlay_vtbl
+{
+ struct IFramebuffer_vtbl iframebuffer;
+
+ nsresult (*GetX)(IFramebufferOverlay *pThis, PRUint32 *x);
+
+ nsresult (*GetY)(IFramebufferOverlay *pThis, PRUint32 *y);
+
+ nsresult (*GetVisible)(IFramebufferOverlay *pThis, PRBool *visible);
+ nsresult (*SetVisible)(IFramebufferOverlay *pThis, PRBool visible);
+
+ nsresult (*GetAlpha)(IFramebufferOverlay *pThis, PRUint32 *alpha);
+ nsresult (*SetAlpha)(IFramebufferOverlay *pThis, PRUint32 alpha);
+
+ nsresult (*Move)(
+ IFramebufferOverlay *pThis,
+ PRUint32 x,
+ PRUint32 y
+ );
+
+};
+
+struct IFramebufferOverlay
+{
+ struct IFramebufferOverlay_vtbl *vtbl;
+};
+/* End of struct IFramebufferOverlay Declaration */
+
+
+/* Start of struct IDisplay Declaration */
+#define IDISPLAY_IID_STR "09EED313-CD56-4D06-BD56-FAC0F716B5DD"
+#define IDISPLAY_IID { \
+ 0x09EED313, 0xCD56, 0x4D06, \
+ { 0xBD, 0x56, 0xFA, 0xC0, 0xF7, 0x16, 0xB5, 0xDD } \
+}
+struct IDisplay_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetScreenResolution)(
+ IDisplay *pThis,
+ PRUint32 screenId,
+ PRUint32 * width,
+ PRUint32 * height,
+ PRUint32 * bitsPerPixel
+ );
+
+ nsresult (*SetFramebuffer)(
+ IDisplay *pThis,
+ PRUint32 screenId,
+ IFramebuffer * framebuffer
+ );
+
+ nsresult (*GetFramebuffer)(
+ IDisplay *pThis,
+ PRUint32 screenId,
+ IFramebuffer * * framebuffer,
+ PRInt32 * xOrigin,
+ PRInt32 * yOrigin
+ );
+
+ nsresult (*SetVideoModeHint)(
+ IDisplay *pThis,
+ PRUint32 width,
+ PRUint32 height,
+ PRUint32 bitsPerPixel,
+ PRUint32 display
+ );
+
+ nsresult (*SetSeamlessMode)(
+ IDisplay *pThis,
+ PRBool enabled
+ );
+
+ nsresult (*TakeScreenShot)(
+ IDisplay *pThis,
+ PRUint32 screenId,
+ PRUint8 * address,
+ PRUint32 width,
+ PRUint32 height
+ );
+
+ nsresult (*TakeScreenShotToArray)(
+ IDisplay *pThis,
+ PRUint32 screenId,
+ PRUint32 width,
+ PRUint32 height,
+ PRUint32 *screenDataSize,
+ PRUint8** screenData
+ );
+
+ nsresult (*TakeScreenShotPNGToArray)(
+ IDisplay *pThis,
+ PRUint32 screenId,
+ PRUint32 width,
+ PRUint32 height,
+ PRUint32 *screenDataSize,
+ PRUint8** screenData
+ );
+
+ nsresult (*DrawToScreen)(
+ IDisplay *pThis,
+ PRUint32 screenId,
+ PRUint8 * address,
+ PRUint32 x,
+ PRUint32 y,
+ PRUint32 width,
+ PRUint32 height
+ );
+
+ nsresult (*InvalidateAndUpdate)(IDisplay *pThis );
+
+ nsresult (*ResizeCompleted)(
+ IDisplay *pThis,
+ PRUint32 screenId
+ );
+
+ nsresult (*CompleteVHWACommand)(
+ IDisplay *pThis,
+ PRUint8 * command
+ );
+
+};
+
+struct IDisplay
+{
+ struct IDisplay_vtbl *vtbl;
+};
+/* End of struct IDisplay Declaration */
+
+
+/* Start of struct INetworkAdapter Declaration */
+#define INETWORKADAPTER_IID_STR "8b2e705c-0547-4008-b7bc-788757346092"
+#define INETWORKADAPTER_IID { \
+ 0x8b2e705c, 0x0547, 0x4008, \
+ { 0xb7, 0xbc, 0x78, 0x87, 0x57, 0x34, 0x60, 0x92 } \
+}
+struct INetworkAdapter_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetAdapterType)(INetworkAdapter *pThis, PRUint32 *adapterType);
+ nsresult (*SetAdapterType)(INetworkAdapter *pThis, PRUint32 adapterType);
+
+ nsresult (*GetSlot)(INetworkAdapter *pThis, PRUint32 *slot);
+
+ nsresult (*GetEnabled)(INetworkAdapter *pThis, PRBool *enabled);
+ nsresult (*SetEnabled)(INetworkAdapter *pThis, PRBool enabled);
+
+ nsresult (*GetMACAddress)(INetworkAdapter *pThis, PRUnichar * *MACAddress);
+ nsresult (*SetMACAddress)(INetworkAdapter *pThis, PRUnichar * MACAddress);
+
+ nsresult (*GetAttachmentType)(INetworkAdapter *pThis, PRUint32 *attachmentType);
+ nsresult (*SetAttachmentType)(INetworkAdapter *pThis, PRUint32 attachmentType);
+
+ nsresult (*GetBridgedInterface)(INetworkAdapter *pThis, PRUnichar * *bridgedInterface);
+ nsresult (*SetBridgedInterface)(INetworkAdapter *pThis, PRUnichar * bridgedInterface);
+
+ nsresult (*GetHostOnlyInterface)(INetworkAdapter *pThis, PRUnichar * *hostOnlyInterface);
+ nsresult (*SetHostOnlyInterface)(INetworkAdapter *pThis, PRUnichar * hostOnlyInterface);
+
+ nsresult (*GetInternalNetwork)(INetworkAdapter *pThis, PRUnichar * *internalNetwork);
+ nsresult (*SetInternalNetwork)(INetworkAdapter *pThis, PRUnichar * internalNetwork);
+
+ nsresult (*GetNATNetwork)(INetworkAdapter *pThis, PRUnichar * *NATNetwork);
+ nsresult (*SetNATNetwork)(INetworkAdapter *pThis, PRUnichar * NATNetwork);
+
+ nsresult (*GetGenericDriver)(INetworkAdapter *pThis, PRUnichar * *genericDriver);
+ nsresult (*SetGenericDriver)(INetworkAdapter *pThis, PRUnichar * genericDriver);
+
+ nsresult (*GetCableConnected)(INetworkAdapter *pThis, PRBool *cableConnected);
+ nsresult (*SetCableConnected)(INetworkAdapter *pThis, PRBool cableConnected);
+
+ nsresult (*GetLineSpeed)(INetworkAdapter *pThis, PRUint32 *lineSpeed);
+ nsresult (*SetLineSpeed)(INetworkAdapter *pThis, PRUint32 lineSpeed);
+
+ nsresult (*GetPromiscModePolicy)(INetworkAdapter *pThis, PRUint32 *promiscModePolicy);
+ nsresult (*SetPromiscModePolicy)(INetworkAdapter *pThis, PRUint32 promiscModePolicy);
+
+ nsresult (*GetTraceEnabled)(INetworkAdapter *pThis, PRBool *traceEnabled);
+ nsresult (*SetTraceEnabled)(INetworkAdapter *pThis, PRBool traceEnabled);
+
+ nsresult (*GetTraceFile)(INetworkAdapter *pThis, PRUnichar * *traceFile);
+ nsresult (*SetTraceFile)(INetworkAdapter *pThis, PRUnichar * traceFile);
+
+ nsresult (*GetNatDriver)(INetworkAdapter *pThis, INATEngine * *natDriver);
+
+ nsresult (*GetBootPriority)(INetworkAdapter *pThis, PRUint32 *bootPriority);
+ nsresult (*SetBootPriority)(INetworkAdapter *pThis, PRUint32 bootPriority);
+
+ nsresult (*GetBandwidthGroup)(INetworkAdapter *pThis, IBandwidthGroup * *bandwidthGroup);
+ nsresult (*SetBandwidthGroup)(INetworkAdapter *pThis, IBandwidthGroup * bandwidthGroup);
+
+ nsresult (*GetProperty)(
+ INetworkAdapter *pThis,
+ PRUnichar * key,
+ PRUnichar * * value
+ );
+
+ nsresult (*SetProperty)(
+ INetworkAdapter *pThis,
+ PRUnichar * key,
+ PRUnichar * value
+ );
+
+ nsresult (*GetProperties)(
+ INetworkAdapter *pThis,
+ PRUnichar * names,
+ PRUint32 *returnNamesSize,
+ PRUnichar *** returnNames,
+ PRUint32 *returnValuesSize,
+ PRUnichar *** returnValues
+ );
+
+};
+
+struct INetworkAdapter
+{
+ struct INetworkAdapter_vtbl *vtbl;
+};
+/* End of struct INetworkAdapter Declaration */
+
+
+/* Start of struct ISerialPort Declaration */
+#define ISERIALPORT_IID_STR "937f6970-5103-4745-b78e-d28dcf1479a8"
+#define ISERIALPORT_IID { \
+ 0x937f6970, 0x5103, 0x4745, \
+ { 0xb7, 0x8e, 0xd2, 0x8d, 0xcf, 0x14, 0x79, 0xa8 } \
+}
+struct ISerialPort_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetSlot)(ISerialPort *pThis, PRUint32 *slot);
+
+ nsresult (*GetEnabled)(ISerialPort *pThis, PRBool *enabled);
+ nsresult (*SetEnabled)(ISerialPort *pThis, PRBool enabled);
+
+ nsresult (*GetIOBase)(ISerialPort *pThis, PRUint32 *IOBase);
+ nsresult (*SetIOBase)(ISerialPort *pThis, PRUint32 IOBase);
+
+ nsresult (*GetIRQ)(ISerialPort *pThis, PRUint32 *IRQ);
+ nsresult (*SetIRQ)(ISerialPort *pThis, PRUint32 IRQ);
+
+ nsresult (*GetHostMode)(ISerialPort *pThis, PRUint32 *hostMode);
+ nsresult (*SetHostMode)(ISerialPort *pThis, PRUint32 hostMode);
+
+ nsresult (*GetServer)(ISerialPort *pThis, PRBool *server);
+ nsresult (*SetServer)(ISerialPort *pThis, PRBool server);
+
+ nsresult (*GetPath)(ISerialPort *pThis, PRUnichar * *path);
+ nsresult (*SetPath)(ISerialPort *pThis, PRUnichar * path);
+
+};
+
+struct ISerialPort
+{
+ struct ISerialPort_vtbl *vtbl;
+};
+/* End of struct ISerialPort Declaration */
+
+
+/* Start of struct IParallelPort Declaration */
+#define IPARALLELPORT_IID_STR "0c925f06-dd10-4b77-8de8-294d738c3214"
+#define IPARALLELPORT_IID { \
+ 0x0c925f06, 0xdd10, 0x4b77, \
+ { 0x8d, 0xe8, 0x29, 0x4d, 0x73, 0x8c, 0x32, 0x14 } \
+}
+struct IParallelPort_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetSlot)(IParallelPort *pThis, PRUint32 *slot);
+
+ nsresult (*GetEnabled)(IParallelPort *pThis, PRBool *enabled);
+ nsresult (*SetEnabled)(IParallelPort *pThis, PRBool enabled);
+
+ nsresult (*GetIOBase)(IParallelPort *pThis, PRUint32 *IOBase);
+ nsresult (*SetIOBase)(IParallelPort *pThis, PRUint32 IOBase);
+
+ nsresult (*GetIRQ)(IParallelPort *pThis, PRUint32 *IRQ);
+ nsresult (*SetIRQ)(IParallelPort *pThis, PRUint32 IRQ);
+
+ nsresult (*GetPath)(IParallelPort *pThis, PRUnichar * *path);
+ nsresult (*SetPath)(IParallelPort *pThis, PRUnichar * path);
+
+};
+
+struct IParallelPort
+{
+ struct IParallelPort_vtbl *vtbl;
+};
+/* End of struct IParallelPort Declaration */
+
+
+/* Start of struct IMachineDebugger Declaration */
+#define IMACHINEDEBUGGER_IID_STR "1bfd2fa9-0d91-44d3-9515-368dcbb3eb4d"
+#define IMACHINEDEBUGGER_IID { \
+ 0x1bfd2fa9, 0x0d91, 0x44d3, \
+ { 0x95, 0x15, 0x36, 0x8d, 0xcb, 0xb3, 0xeb, 0x4d } \
+}
+struct IMachineDebugger_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetSinglestep)(IMachineDebugger *pThis, PRBool *singlestep);
+ nsresult (*SetSinglestep)(IMachineDebugger *pThis, PRBool singlestep);
+
+ nsresult (*GetRecompileUser)(IMachineDebugger *pThis, PRBool *recompileUser);
+ nsresult (*SetRecompileUser)(IMachineDebugger *pThis, PRBool recompileUser);
+
+ nsresult (*GetRecompileSupervisor)(IMachineDebugger *pThis, PRBool *recompileSupervisor);
+ nsresult (*SetRecompileSupervisor)(IMachineDebugger *pThis, PRBool recompileSupervisor);
+
+ nsresult (*GetPATMEnabled)(IMachineDebugger *pThis, PRBool *PATMEnabled);
+ nsresult (*SetPATMEnabled)(IMachineDebugger *pThis, PRBool PATMEnabled);
+
+ nsresult (*GetCSAMEnabled)(IMachineDebugger *pThis, PRBool *CSAMEnabled);
+ nsresult (*SetCSAMEnabled)(IMachineDebugger *pThis, PRBool CSAMEnabled);
+
+ nsresult (*GetLogEnabled)(IMachineDebugger *pThis, PRBool *logEnabled);
+ nsresult (*SetLogEnabled)(IMachineDebugger *pThis, PRBool logEnabled);
+
+ nsresult (*GetLogFlags)(IMachineDebugger *pThis, PRUnichar * *logFlags);
+
+ nsresult (*GetLogGroups)(IMachineDebugger *pThis, PRUnichar * *logGroups);
+
+ nsresult (*GetLogDestinations)(IMachineDebugger *pThis, PRUnichar * *logDestinations);
+
+ nsresult (*GetHWVirtExEnabled)(IMachineDebugger *pThis, PRBool *HWVirtExEnabled);
+
+ nsresult (*GetHWVirtExNestedPagingEnabled)(IMachineDebugger *pThis, PRBool *HWVirtExNestedPagingEnabled);
+
+ nsresult (*GetHWVirtExVPIDEnabled)(IMachineDebugger *pThis, PRBool *HWVirtExVPIDEnabled);
+
+ nsresult (*GetOSName)(IMachineDebugger *pThis, PRUnichar * *OSName);
+
+ nsresult (*GetOSVersion)(IMachineDebugger *pThis, PRUnichar * *OSVersion);
+
+ nsresult (*GetPAEEnabled)(IMachineDebugger *pThis, PRBool *PAEEnabled);
+
+ nsresult (*GetVirtualTimeRate)(IMachineDebugger *pThis, PRUint32 *virtualTimeRate);
+ nsresult (*SetVirtualTimeRate)(IMachineDebugger *pThis, PRUint32 virtualTimeRate);
+
+ nsresult (*GetVM)(IMachineDebugger *pThis, PRInt64 *VM);
+
+ nsresult (*DumpGuestCore)(
+ IMachineDebugger *pThis,
+ PRUnichar * filename,
+ PRUnichar * compression
+ );
+
+ nsresult (*DumpHostProcessCore)(
+ IMachineDebugger *pThis,
+ PRUnichar * filename,
+ PRUnichar * compression
+ );
+
+ nsresult (*Info)(
+ IMachineDebugger *pThis,
+ PRUnichar * name,
+ PRUnichar * args,
+ PRUnichar * * info
+ );
+
+ nsresult (*InjectNMI)(IMachineDebugger *pThis );
+
+ nsresult (*ModifyLogGroups)(
+ IMachineDebugger *pThis,
+ PRUnichar * settings
+ );
+
+ nsresult (*ModifyLogFlags)(
+ IMachineDebugger *pThis,
+ PRUnichar * settings
+ );
+
+ nsresult (*ModifyLogDestinations)(
+ IMachineDebugger *pThis,
+ PRUnichar * settings
+ );
+
+ nsresult (*ReadPhysicalMemory)(
+ IMachineDebugger *pThis,
+ PRInt64 address,
+ PRUint32 size,
+ PRUint32 *bytesSize,
+ PRUint8** bytes
+ );
+
+ nsresult (*WritePhysicalMemory)(
+ IMachineDebugger *pThis,
+ PRInt64 address,
+ PRUint32 size,
+ PRUint32 bytesSize,
+ PRUint8* bytes
+ );
+
+ nsresult (*ReadVirtualMemory)(
+ IMachineDebugger *pThis,
+ PRUint32 cpuId,
+ PRInt64 address,
+ PRUint32 size,
+ PRUint32 *bytesSize,
+ PRUint8** bytes
+ );
+
+ nsresult (*WriteVirtualMemory)(
+ IMachineDebugger *pThis,
+ PRUint32 cpuId,
+ PRInt64 address,
+ PRUint32 size,
+ PRUint32 bytesSize,
+ PRUint8* bytes
+ );
+
+ nsresult (*DetectOS)(
+ IMachineDebugger *pThis,
+ PRUnichar * * os
+ );
+
+ nsresult (*GetRegister)(
+ IMachineDebugger *pThis,
+ PRUint32 cpuId,
+ PRUnichar * name,
+ PRUnichar * * value
+ );
+
+ nsresult (*GetRegisters)(
+ IMachineDebugger *pThis,
+ PRUint32 cpuId,
+ PRUint32 *namesSize,
+ PRUnichar *** names,
+ PRUint32 *valuesSize,
+ PRUnichar *** values
+ );
+
+ nsresult (*SetRegister)(
+ IMachineDebugger *pThis,
+ PRUint32 cpuId,
+ PRUnichar * name,
+ PRUnichar * value
+ );
+
+ nsresult (*SetRegisters)(
+ IMachineDebugger *pThis,
+ PRUint32 cpuId,
+ PRUint32 namesSize,
+ PRUnichar ** names,
+ PRUint32 valuesSize,
+ PRUnichar ** values
+ );
+
+ nsresult (*DumpGuestStack)(
+ IMachineDebugger *pThis,
+ PRUint32 cpuId,
+ PRUnichar * * stack
+ );
+
+ nsresult (*ResetStats)(
+ IMachineDebugger *pThis,
+ PRUnichar * pattern
+ );
+
+ nsresult (*DumpStats)(
+ IMachineDebugger *pThis,
+ PRUnichar * pattern
+ );
+
+ nsresult (*GetStats)(
+ IMachineDebugger *pThis,
+ PRUnichar * pattern,
+ PRBool withDescriptions,
+ PRUnichar * * stats
+ );
+
+};
+
+struct IMachineDebugger
+{
+ struct IMachineDebugger_vtbl *vtbl;
+};
+/* End of struct IMachineDebugger Declaration */
+
+
+/* Start of struct IUSBController Declaration */
+#define IUSBCONTROLLER_IID_STR "6fdcccc5-abd3-4fec-9387-2ad3914fc4a8"
+#define IUSBCONTROLLER_IID { \
+ 0x6fdcccc5, 0xabd3, 0x4fec, \
+ { 0x93, 0x87, 0x2a, 0xd3, 0x91, 0x4f, 0xc4, 0xa8 } \
+}
+struct IUSBController_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetEnabled)(IUSBController *pThis, PRBool *enabled);
+ nsresult (*SetEnabled)(IUSBController *pThis, PRBool enabled);
+
+ nsresult (*GetEnabledEhci)(IUSBController *pThis, PRBool *enabledEhci);
+ nsresult (*SetEnabledEhci)(IUSBController *pThis, PRBool enabledEhci);
+
+ nsresult (*GetProxyAvailable)(IUSBController *pThis, PRBool *proxyAvailable);
+
+ nsresult (*GetUSBStandard)(IUSBController *pThis, PRUint16 *USBStandard);
+
+ nsresult (*GetDeviceFilters)(IUSBController *pThis, PRUint32 *deviceFiltersSize, IUSBDeviceFilter * **deviceFilters);
+
+ nsresult (*CreateDeviceFilter)(
+ IUSBController *pThis,
+ PRUnichar * name,
+ IUSBDeviceFilter * * filter
+ );
+
+ nsresult (*InsertDeviceFilter)(
+ IUSBController *pThis,
+ PRUint32 position,
+ IUSBDeviceFilter * filter
+ );
+
+ nsresult (*RemoveDeviceFilter)(
+ IUSBController *pThis,
+ PRUint32 position,
+ IUSBDeviceFilter * * filter
+ );
+
+};
+
+struct IUSBController
+{
+ struct IUSBController_vtbl *vtbl;
+};
+/* End of struct IUSBController Declaration */
+
+
+/* Start of struct IUSBDevice Declaration */
+#define IUSBDEVICE_IID_STR "f8967b0b-4483-400f-92b5-8b675d98a85b"
+#define IUSBDEVICE_IID { \
+ 0xf8967b0b, 0x4483, 0x400f, \
+ { 0x92, 0xb5, 0x8b, 0x67, 0x5d, 0x98, 0xa8, 0x5b } \
+}
+struct IUSBDevice_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetId)(IUSBDevice *pThis, PRUnichar * *id);
+
+ nsresult (*GetVendorId)(IUSBDevice *pThis, PRUint16 *vendorId);
+
+ nsresult (*GetProductId)(IUSBDevice *pThis, PRUint16 *productId);
+
+ nsresult (*GetRevision)(IUSBDevice *pThis, PRUint16 *revision);
+
+ nsresult (*GetManufacturer)(IUSBDevice *pThis, PRUnichar * *manufacturer);
+
+ nsresult (*GetProduct)(IUSBDevice *pThis, PRUnichar * *product);
+
+ nsresult (*GetSerialNumber)(IUSBDevice *pThis, PRUnichar * *serialNumber);
+
+ nsresult (*GetAddress)(IUSBDevice *pThis, PRUnichar * *address);
+
+ nsresult (*GetPort)(IUSBDevice *pThis, PRUint16 *port);
+
+ nsresult (*GetVersion)(IUSBDevice *pThis, PRUint16 *version);
+
+ nsresult (*GetPortVersion)(IUSBDevice *pThis, PRUint16 *portVersion);
+
+ nsresult (*GetRemote)(IUSBDevice *pThis, PRBool *remote);
+
+};
+
+struct IUSBDevice
+{
+ struct IUSBDevice_vtbl *vtbl;
+};
+/* End of struct IUSBDevice Declaration */
+
+
+/* Start of struct IUSBDeviceFilter Declaration */
+#define IUSBDEVICEFILTER_IID_STR "d6831fb4-1a94-4c2c-96ef-8d0d6192066d"
+#define IUSBDEVICEFILTER_IID { \
+ 0xd6831fb4, 0x1a94, 0x4c2c, \
+ { 0x96, 0xef, 0x8d, 0x0d, 0x61, 0x92, 0x06, 0x6d } \
+}
+struct IUSBDeviceFilter_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetName)(IUSBDeviceFilter *pThis, PRUnichar * *name);
+ nsresult (*SetName)(IUSBDeviceFilter *pThis, PRUnichar * name);
+
+ nsresult (*GetActive)(IUSBDeviceFilter *pThis, PRBool *active);
+ nsresult (*SetActive)(IUSBDeviceFilter *pThis, PRBool active);
+
+ nsresult (*GetVendorId)(IUSBDeviceFilter *pThis, PRUnichar * *vendorId);
+ nsresult (*SetVendorId)(IUSBDeviceFilter *pThis, PRUnichar * vendorId);
+
+ nsresult (*GetProductId)(IUSBDeviceFilter *pThis, PRUnichar * *productId);
+ nsresult (*SetProductId)(IUSBDeviceFilter *pThis, PRUnichar * productId);
+
+ nsresult (*GetRevision)(IUSBDeviceFilter *pThis, PRUnichar * *revision);
+ nsresult (*SetRevision)(IUSBDeviceFilter *pThis, PRUnichar * revision);
+
+ nsresult (*GetManufacturer)(IUSBDeviceFilter *pThis, PRUnichar * *manufacturer);
+ nsresult (*SetManufacturer)(IUSBDeviceFilter *pThis, PRUnichar * manufacturer);
+
+ nsresult (*GetProduct)(IUSBDeviceFilter *pThis, PRUnichar * *product);
+ nsresult (*SetProduct)(IUSBDeviceFilter *pThis, PRUnichar * product);
+
+ nsresult (*GetSerialNumber)(IUSBDeviceFilter *pThis, PRUnichar * *serialNumber);
+ nsresult (*SetSerialNumber)(IUSBDeviceFilter *pThis, PRUnichar * serialNumber);
+
+ nsresult (*GetPort)(IUSBDeviceFilter *pThis, PRUnichar * *port);
+ nsresult (*SetPort)(IUSBDeviceFilter *pThis, PRUnichar * port);
+
+ nsresult (*GetRemote)(IUSBDeviceFilter *pThis, PRUnichar * *remote);
+ nsresult (*SetRemote)(IUSBDeviceFilter *pThis, PRUnichar * remote);
+
+ nsresult (*GetMaskedInterfaces)(IUSBDeviceFilter *pThis, PRUint32 *maskedInterfaces);
+ nsresult (*SetMaskedInterfaces)(IUSBDeviceFilter *pThis, PRUint32 maskedInterfaces);
+
+};
+
+struct IUSBDeviceFilter
+{
+ struct IUSBDeviceFilter_vtbl *vtbl;
+};
+/* End of struct IUSBDeviceFilter Declaration */
+
+
+/* Start of struct IHostUSBDevice Declaration */
+#define IHOSTUSBDEVICE_IID_STR "173b4b44-d268-4334-a00d-b6521c9a740a"
+#define IHOSTUSBDEVICE_IID { \
+ 0x173b4b44, 0xd268, 0x4334, \
+ { 0xa0, 0x0d, 0xb6, 0x52, 0x1c, 0x9a, 0x74, 0x0a } \
+}
+struct IHostUSBDevice_vtbl
+{
+ struct IUSBDevice_vtbl iusbdevice;
+
+ nsresult (*GetState)(IHostUSBDevice *pThis, PRUint32 *state);
+
+};
+
+struct IHostUSBDevice
+{
+ struct IHostUSBDevice_vtbl *vtbl;
+};
+/* End of struct IHostUSBDevice Declaration */
+
+
+/* Start of struct IHostUSBDeviceFilter Declaration */
+#define IHOSTUSBDEVICEFILTER_IID_STR "4cc70246-d74a-400f-8222-3900489c0374"
+#define IHOSTUSBDEVICEFILTER_IID { \
+ 0x4cc70246, 0xd74a, 0x400f, \
+ { 0x82, 0x22, 0x39, 0x00, 0x48, 0x9c, 0x03, 0x74 } \
+}
+struct IHostUSBDeviceFilter_vtbl
+{
+ struct IUSBDeviceFilter_vtbl iusbdevicefilter;
+
+ nsresult (*GetAction)(IHostUSBDeviceFilter *pThis, PRUint32 *action);
+ nsresult (*SetAction)(IHostUSBDeviceFilter *pThis, PRUint32 action);
+
+};
+
+struct IHostUSBDeviceFilter
+{
+ struct IHostUSBDeviceFilter_vtbl *vtbl;
+};
+/* End of struct IHostUSBDeviceFilter Declaration */
+
+
+/* Start of struct IAudioAdapter Declaration */
+#define IAUDIOADAPTER_IID_STR "921873db-5f3f-4b69-91f9-7be9e535a2cb"
+#define IAUDIOADAPTER_IID { \
+ 0x921873db, 0x5f3f, 0x4b69, \
+ { 0x91, 0xf9, 0x7b, 0xe9, 0xe5, 0x35, 0xa2, 0xcb } \
+}
+struct IAudioAdapter_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetEnabled)(IAudioAdapter *pThis, PRBool *enabled);
+ nsresult (*SetEnabled)(IAudioAdapter *pThis, PRBool enabled);
+
+ nsresult (*GetAudioController)(IAudioAdapter *pThis, PRUint32 *audioController);
+ nsresult (*SetAudioController)(IAudioAdapter *pThis, PRUint32 audioController);
+
+ nsresult (*GetAudioDriver)(IAudioAdapter *pThis, PRUint32 *audioDriver);
+ nsresult (*SetAudioDriver)(IAudioAdapter *pThis, PRUint32 audioDriver);
+
+};
+
+struct IAudioAdapter
+{
+ struct IAudioAdapter_vtbl *vtbl;
+};
+/* End of struct IAudioAdapter Declaration */
+
+
+/* Start of struct IVRDEServer Declaration */
+#define IVRDESERVER_IID_STR "d38de40a-c2c1-4e95-b5a4-167b05f5694c"
+#define IVRDESERVER_IID { \
+ 0xd38de40a, 0xc2c1, 0x4e95, \
+ { 0xb5, 0xa4, 0x16, 0x7b, 0x05, 0xf5, 0x69, 0x4c } \
+}
+struct IVRDEServer_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetEnabled)(IVRDEServer *pThis, PRBool *enabled);
+ nsresult (*SetEnabled)(IVRDEServer *pThis, PRBool enabled);
+
+ nsresult (*GetAuthType)(IVRDEServer *pThis, PRUint32 *authType);
+ nsresult (*SetAuthType)(IVRDEServer *pThis, PRUint32 authType);
+
+ nsresult (*GetAuthTimeout)(IVRDEServer *pThis, PRUint32 *authTimeout);
+ nsresult (*SetAuthTimeout)(IVRDEServer *pThis, PRUint32 authTimeout);
+
+ nsresult (*GetAllowMultiConnection)(IVRDEServer *pThis, PRBool *allowMultiConnection);
+ nsresult (*SetAllowMultiConnection)(IVRDEServer *pThis, PRBool allowMultiConnection);
+
+ nsresult (*GetReuseSingleConnection)(IVRDEServer *pThis, PRBool *reuseSingleConnection);
+ nsresult (*SetReuseSingleConnection)(IVRDEServer *pThis, PRBool reuseSingleConnection);
+
+ nsresult (*GetVRDEExtPack)(IVRDEServer *pThis, PRUnichar * *VRDEExtPack);
+ nsresult (*SetVRDEExtPack)(IVRDEServer *pThis, PRUnichar * VRDEExtPack);
+
+ nsresult (*GetAuthLibrary)(IVRDEServer *pThis, PRUnichar * *authLibrary);
+ nsresult (*SetAuthLibrary)(IVRDEServer *pThis, PRUnichar * authLibrary);
+
+ nsresult (*GetVRDEProperties)(IVRDEServer *pThis, PRUint32 *VRDEPropertiesSize, PRUnichar * **VRDEProperties);
+
+ nsresult (*SetVRDEProperty)(
+ IVRDEServer *pThis,
+ PRUnichar * key,
+ PRUnichar * value
+ );
+
+ nsresult (*GetVRDEProperty)(
+ IVRDEServer *pThis,
+ PRUnichar * key,
+ PRUnichar * * value
+ );
+
+};
+
+struct IVRDEServer
+{
+ struct IVRDEServer_vtbl *vtbl;
+};
+/* End of struct IVRDEServer Declaration */
+
+
+/* Start of struct ISharedFolder Declaration */
+#define ISHAREDFOLDER_IID_STR "8388da11-b559-4574-a5b7-2bd7acd5cef8"
+#define ISHAREDFOLDER_IID { \
+ 0x8388da11, 0xb559, 0x4574, \
+ { 0xa5, 0xb7, 0x2b, 0xd7, 0xac, 0xd5, 0xce, 0xf8 } \
+}
+struct ISharedFolder_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetName)(ISharedFolder *pThis, PRUnichar * *name);
+
+ nsresult (*GetHostPath)(ISharedFolder *pThis, PRUnichar * *hostPath);
+
+ nsresult (*GetAccessible)(ISharedFolder *pThis, PRBool *accessible);
+
+ nsresult (*GetWritable)(ISharedFolder *pThis, PRBool *writable);
+
+ nsresult (*GetAutoMount)(ISharedFolder *pThis, PRBool *autoMount);
+
+ nsresult (*GetLastAccessError)(ISharedFolder *pThis, PRUnichar * *lastAccessError);
+
+};
+
+struct ISharedFolder
+{
+ struct ISharedFolder_vtbl *vtbl;
+};
+/* End of struct ISharedFolder Declaration */
+
+
+/* Start of struct IInternalSessionControl Declaration */
+#define IINTERNALSESSIONCONTROL_IID_STR "0bdda5da-67c8-47be-a610-b83a7fa3e8b6"
+#define IINTERNALSESSIONCONTROL_IID { \
+ 0x0bdda5da, 0x67c8, 0x47be, \
+ { 0xa6, 0x10, 0xb8, 0x3a, 0x7f, 0xa3, 0xe8, 0xb6 } \
+}
+struct IInternalSessionControl_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetPID)(
+ IInternalSessionControl *pThis,
+ PRUint32 * pid
+ );
+
+ nsresult (*GetRemoteConsole)(
+ IInternalSessionControl *pThis,
+ IConsole * * console
+ );
+
+ nsresult (*AssignMachine)(
+ IInternalSessionControl *pThis,
+ IMachine * machine
+ );
+
+ nsresult (*AssignRemoteMachine)(
+ IInternalSessionControl *pThis,
+ IMachine * machine,
+ IConsole * console
+ );
+
+ nsresult (*UpdateMachineState)(
+ IInternalSessionControl *pThis,
+ PRUint32 aMachineState
+ );
+
+ nsresult (*Uninitialize)(IInternalSessionControl *pThis );
+
+ nsresult (*OnNetworkAdapterChange)(
+ IInternalSessionControl *pThis,
+ INetworkAdapter * networkAdapter,
+ PRBool changeAdapter
+ );
+
+ nsresult (*OnSerialPortChange)(
+ IInternalSessionControl *pThis,
+ ISerialPort * serialPort
+ );
+
+ nsresult (*OnParallelPortChange)(
+ IInternalSessionControl *pThis,
+ IParallelPort * parallelPort
+ );
+
+ nsresult (*OnStorageControllerChange)(IInternalSessionControl *pThis );
+
+ nsresult (*OnMediumChange)(
+ IInternalSessionControl *pThis,
+ IMediumAttachment * mediumAttachment,
+ PRBool force
+ );
+
+ nsresult (*OnStorageDeviceChange)(
+ IInternalSessionControl *pThis,
+ IMediumAttachment * mediumAttachment,
+ PRBool remove
+ );
+
+ nsresult (*OnCPUChange)(
+ IInternalSessionControl *pThis,
+ PRUint32 cpu,
+ PRBool add
+ );
+
+ nsresult (*OnCPUExecutionCapChange)(
+ IInternalSessionControl *pThis,
+ PRUint32 executionCap
+ );
+
+ nsresult (*OnVRDEServerChange)(
+ IInternalSessionControl *pThis,
+ PRBool restart
+ );
+
+ nsresult (*OnUSBControllerChange)(IInternalSessionControl *pThis );
+
+ nsresult (*OnSharedFolderChange)(
+ IInternalSessionControl *pThis,
+ PRBool global
+ );
+
+ nsresult (*OnUSBDeviceAttach)(
+ IInternalSessionControl *pThis,
+ IUSBDevice * device,
+ IVirtualBoxErrorInfo * error,
+ PRUint32 maskedInterfaces
+ );
+
+ nsresult (*OnUSBDeviceDetach)(
+ IInternalSessionControl *pThis,
+ PRUnichar * id,
+ IVirtualBoxErrorInfo * error
+ );
+
+ nsresult (*OnShowWindow)(
+ IInternalSessionControl *pThis,
+ PRBool check,
+ PRBool * canShow,
+ PRInt64 * winId
+ );
+
+ nsresult (*OnBandwidthGroupChange)(
+ IInternalSessionControl *pThis,
+ IBandwidthGroup * bandwidthGroup
+ );
+
+ nsresult (*AccessGuestProperty)(
+ IInternalSessionControl *pThis,
+ PRUnichar * name,
+ PRUnichar * value,
+ PRUnichar * flags,
+ PRBool isSetter,
+ PRUnichar * * retValue,
+ PRInt64 * retTimestamp,
+ PRUnichar * * retFlags
+ );
+
+ nsresult (*EnumerateGuestProperties)(
+ IInternalSessionControl *pThis,
+ PRUnichar * patterns,
+ PRUint32 *keySize,
+ PRUnichar *** key,
+ PRUint32 *valueSize,
+ PRUnichar *** value,
+ PRUint32 *timestampSize,
+ PRInt64* timestamp,
+ PRUint32 *flagsSize,
+ PRUnichar *** flags
+ );
+
+ nsresult (*OnlineMergeMedium)(
+ IInternalSessionControl *pThis,
+ IMediumAttachment * mediumAttachment,
+ PRUint32 sourceIdx,
+ PRUint32 targetIdx,
+ IMedium * source,
+ IMedium * target,
+ PRBool mergeForward,
+ IMedium * parentForTarget,
+ PRUint32 childrenToReparentSize,
+ IMedium ** childrenToReparent,
+ IProgress * progress
+ );
+
+};
+
+struct IInternalSessionControl
+{
+ struct IInternalSessionControl_vtbl *vtbl;
+};
+/* End of struct IInternalSessionControl Declaration */
+
+
+/* Start of struct ISession Declaration */
+#define ISESSION_IID_STR "12F4DCDB-12B2-4EC1-B7CD-DDD9F6C5BF4D"
+#define ISESSION_IID { \
+ 0x12F4DCDB, 0x12B2, 0x4EC1, \
+ { 0xB7, 0xCD, 0xDD, 0xD9, 0xF6, 0xC5, 0xBF, 0x4D } \
+}
+struct ISession_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetState)(ISession *pThis, PRUint32 *state);
+
+ nsresult (*GetType)(ISession *pThis, PRUint32 *type);
+
+ nsresult (*GetMachine)(ISession *pThis, IMachine * *machine);
+
+ nsresult (*GetConsole)(ISession *pThis, IConsole * *console);
+
+ nsresult (*UnlockMachine)(ISession *pThis );
+
+};
+
+struct ISession
+{
+ struct ISession_vtbl *vtbl;
+};
+/* End of struct ISession Declaration */
+
+
+/* Start of struct IStorageController Declaration */
+#define ISTORAGECONTROLLER_IID_STR "a1556333-09b6-46d9-bfb7-fc239b7fbe1e"
+#define ISTORAGECONTROLLER_IID { \
+ 0xa1556333, 0x09b6, 0x46d9, \
+ { 0xbf, 0xb7, 0xfc, 0x23, 0x9b, 0x7f, 0xbe, 0x1e } \
+}
+struct IStorageController_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetName)(IStorageController *pThis, PRUnichar * *name);
+
+ nsresult (*GetMaxDevicesPerPortCount)(IStorageController *pThis, PRUint32 *maxDevicesPerPortCount);
+
+ nsresult (*GetMinPortCount)(IStorageController *pThis, PRUint32 *minPortCount);
+
+ nsresult (*GetMaxPortCount)(IStorageController *pThis, PRUint32 *maxPortCount);
+
+ nsresult (*GetInstance)(IStorageController *pThis, PRUint32 *instance);
+ nsresult (*SetInstance)(IStorageController *pThis, PRUint32 instance);
+
+ nsresult (*GetPortCount)(IStorageController *pThis, PRUint32 *portCount);
+ nsresult (*SetPortCount)(IStorageController *pThis, PRUint32 portCount);
+
+ nsresult (*GetBus)(IStorageController *pThis, PRUint32 *bus);
+
+ nsresult (*GetControllerType)(IStorageController *pThis, PRUint32 *controllerType);
+ nsresult (*SetControllerType)(IStorageController *pThis, PRUint32 controllerType);
+
+ nsresult (*GetUseHostIOCache)(IStorageController *pThis, PRBool *useHostIOCache);
+ nsresult (*SetUseHostIOCache)(IStorageController *pThis, PRBool useHostIOCache);
+
+ nsresult (*GetBootable)(IStorageController *pThis, PRBool *bootable);
+
+ nsresult (*GetIDEEmulationPort)(
+ IStorageController *pThis,
+ PRInt32 devicePosition,
+ PRInt32 * portNumber
+ );
+
+ nsresult (*SetIDEEmulationPort)(
+ IStorageController *pThis,
+ PRInt32 devicePosition,
+ PRInt32 portNumber
+ );
+
+};
+
+struct IStorageController
+{
+ struct IStorageController_vtbl *vtbl;
+};
+/* End of struct IStorageController Declaration */
+
+
+/* Start of struct IPerformanceMetric Declaration */
+#define IPERFORMANCEMETRIC_IID_STR "2a1a60ae-9345-4019-ad53-d34ba41cbfe9"
+#define IPERFORMANCEMETRIC_IID { \
+ 0x2a1a60ae, 0x9345, 0x4019, \
+ { 0xad, 0x53, 0xd3, 0x4b, 0xa4, 0x1c, 0xbf, 0xe9 } \
+}
+struct IPerformanceMetric_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetMetricName)(IPerformanceMetric *pThis, PRUnichar * *metricName);
+
+ nsresult (*GetObject)(IPerformanceMetric *pThis, nsISupports * *object);
+
+ nsresult (*GetDescription)(IPerformanceMetric *pThis, PRUnichar * *description);
+
+ nsresult (*GetPeriod)(IPerformanceMetric *pThis, PRUint32 *period);
+
+ nsresult (*GetCount)(IPerformanceMetric *pThis, PRUint32 *count);
+
+ nsresult (*GetUnit)(IPerformanceMetric *pThis, PRUnichar * *unit);
+
+ nsresult (*GetMinimumValue)(IPerformanceMetric *pThis, PRInt32 *minimumValue);
+
+ nsresult (*GetMaximumValue)(IPerformanceMetric *pThis, PRInt32 *maximumValue);
+
+};
+
+struct IPerformanceMetric
+{
+ struct IPerformanceMetric_vtbl *vtbl;
+};
+/* End of struct IPerformanceMetric Declaration */
+
+
+/* Start of struct IPerformanceCollector Declaration */
+#define IPERFORMANCECOLLECTOR_IID_STR "e22e1acb-ac4a-43bb-a31c-17321659b0c6"
+#define IPERFORMANCECOLLECTOR_IID { \
+ 0xe22e1acb, 0xac4a, 0x43bb, \
+ { 0xa3, 0x1c, 0x17, 0x32, 0x16, 0x59, 0xb0, 0xc6 } \
+}
+struct IPerformanceCollector_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetMetricNames)(IPerformanceCollector *pThis, PRUint32 *metricNamesSize, PRUnichar * **metricNames);
+
+ nsresult (*GetMetrics)(
+ IPerformanceCollector *pThis,
+ PRUint32 metricNamesSize,
+ PRUnichar ** metricNames,
+ PRUint32 objectsSize,
+ nsISupports ** objects,
+ PRUint32 *metricsSize,
+ IPerformanceMetric *** metrics
+ );
+
+ nsresult (*SetupMetrics)(
+ IPerformanceCollector *pThis,
+ PRUint32 metricNamesSize,
+ PRUnichar ** metricNames,
+ PRUint32 objectsSize,
+ nsISupports ** objects,
+ PRUint32 period,
+ PRUint32 count,
+ PRUint32 *affectedMetricsSize,
+ IPerformanceMetric *** affectedMetrics
+ );
+
+ nsresult (*EnableMetrics)(
+ IPerformanceCollector *pThis,
+ PRUint32 metricNamesSize,
+ PRUnichar ** metricNames,
+ PRUint32 objectsSize,
+ nsISupports ** objects,
+ PRUint32 *affectedMetricsSize,
+ IPerformanceMetric *** affectedMetrics
+ );
+
+ nsresult (*DisableMetrics)(
+ IPerformanceCollector *pThis,
+ PRUint32 metricNamesSize,
+ PRUnichar ** metricNames,
+ PRUint32 objectsSize,
+ nsISupports ** objects,
+ PRUint32 *affectedMetricsSize,
+ IPerformanceMetric *** affectedMetrics
+ );
+
+ nsresult (*QueryMetricsData)(
+ IPerformanceCollector *pThis,
+ PRUint32 metricNamesSize,
+ PRUnichar ** metricNames,
+ PRUint32 objectsSize,
+ nsISupports ** objects,
+ PRUint32 *returnMetricNamesSize,
+ PRUnichar *** returnMetricNames,
+ PRUint32 *returnObjectsSize,
+ nsISupports ** returnObjects,
+ PRUint32 *returnUnitsSize,
+ PRUnichar *** returnUnits,
+ PRUint32 *returnScalesSize,
+ PRUint32* returnScales,
+ PRUint32 *returnSequenceNumbersSize,
+ PRUint32* returnSequenceNumbers,
+ PRUint32 *returnDataIndicesSize,
+ PRUint32* returnDataIndices,
+ PRUint32 *returnDataLengthsSize,
+ PRUint32* returnDataLengths,
+ PRUint32 *returnDataSize,
+ PRInt32** returnData
+ );
+
+};
+
+struct IPerformanceCollector
+{
+ struct IPerformanceCollector_vtbl *vtbl;
+};
+/* End of struct IPerformanceCollector Declaration */
+
+
+/* Start of struct INATEngine Declaration */
+#define INATENGINE_IID_STR "4b286616-eb03-11de-b0fb-1701eca42246"
+#define INATENGINE_IID { \
+ 0x4b286616, 0xeb03, 0x11de, \
+ { 0xb0, 0xfb, 0x17, 0x01, 0xec, 0xa4, 0x22, 0x46 } \
+}
+struct INATEngine_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetNetwork)(INATEngine *pThis, PRUnichar * *network);
+ nsresult (*SetNetwork)(INATEngine *pThis, PRUnichar * network);
+
+ nsresult (*GetHostIP)(INATEngine *pThis, PRUnichar * *hostIP);
+ nsresult (*SetHostIP)(INATEngine *pThis, PRUnichar * hostIP);
+
+ nsresult (*GetTftpPrefix)(INATEngine *pThis, PRUnichar * *tftpPrefix);
+ nsresult (*SetTftpPrefix)(INATEngine *pThis, PRUnichar * tftpPrefix);
+
+ nsresult (*GetTftpBootFile)(INATEngine *pThis, PRUnichar * *tftpBootFile);
+ nsresult (*SetTftpBootFile)(INATEngine *pThis, PRUnichar * tftpBootFile);
+
+ nsresult (*GetTftpNextServer)(INATEngine *pThis, PRUnichar * *tftpNextServer);
+ nsresult (*SetTftpNextServer)(INATEngine *pThis, PRUnichar * tftpNextServer);
+
+ nsresult (*GetAliasMode)(INATEngine *pThis, PRUint32 *aliasMode);
+ nsresult (*SetAliasMode)(INATEngine *pThis, PRUint32 aliasMode);
+
+ nsresult (*GetDnsPassDomain)(INATEngine *pThis, PRBool *dnsPassDomain);
+ nsresult (*SetDnsPassDomain)(INATEngine *pThis, PRBool dnsPassDomain);
+
+ nsresult (*GetDnsProxy)(INATEngine *pThis, PRBool *dnsProxy);
+ nsresult (*SetDnsProxy)(INATEngine *pThis, PRBool dnsProxy);
+
+ nsresult (*GetDnsUseHostResolver)(INATEngine *pThis, PRBool *dnsUseHostResolver);
+ nsresult (*SetDnsUseHostResolver)(INATEngine *pThis, PRBool dnsUseHostResolver);
+
+ nsresult (*GetRedirects)(INATEngine *pThis, PRUint32 *redirectsSize, PRUnichar * **redirects);
+
+ nsresult (*SetNetworkSettings)(
+ INATEngine *pThis,
+ PRUint32 mtu,
+ PRUint32 sockSnd,
+ PRUint32 sockRcv,
+ PRUint32 TcpWndSnd,
+ PRUint32 TcpWndRcv
+ );
+
+ nsresult (*GetNetworkSettings)(
+ INATEngine *pThis,
+ PRUint32 * mtu,
+ PRUint32 * sockSnd,
+ PRUint32 * sockRcv,
+ PRUint32 * TcpWndSnd,
+ PRUint32 * TcpWndRcv
+ );
+
+ nsresult (*AddRedirect)(
+ INATEngine *pThis,
+ PRUnichar * name,
+ PRUint32 proto,
+ PRUnichar * hostIp,
+ PRUint16 hostPort,
+ PRUnichar * guestIp,
+ PRUint16 guestPort
+ );
+
+ nsresult (*RemoveRedirect)(
+ INATEngine *pThis,
+ PRUnichar * name
+ );
+
+};
+
+struct INATEngine
+{
+ struct INATEngine_vtbl *vtbl;
+};
+/* End of struct INATEngine Declaration */
+
+
+/* Start of struct IExtPackPlugIn Declaration */
+#define IEXTPACKPLUGIN_IID_STR "58000040-e718-4746-bbce-4b86d96da461"
+#define IEXTPACKPLUGIN_IID { \
+ 0x58000040, 0xe718, 0x4746, \
+ { 0xbb, 0xce, 0x4b, 0x86, 0xd9, 0x6d, 0xa4, 0x61 } \
+}
+struct IExtPackPlugIn_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetName)(IExtPackPlugIn *pThis, PRUnichar * *name);
+
+ nsresult (*GetDescription)(IExtPackPlugIn *pThis, PRUnichar * *description);
+
+ nsresult (*GetFrontend)(IExtPackPlugIn *pThis, PRUnichar * *frontend);
+
+ nsresult (*GetModulePath)(IExtPackPlugIn *pThis, PRUnichar * *modulePath);
+
+};
+
+struct IExtPackPlugIn
+{
+ struct IExtPackPlugIn_vtbl *vtbl;
+};
+/* End of struct IExtPackPlugIn Declaration */
+
+
+/* Start of struct IExtPackBase Declaration */
+#define IEXTPACKBASE_IID_STR "5ffb0b64-0ad6-467d-af62-1157e7dc3c99"
+#define IEXTPACKBASE_IID { \
+ 0x5ffb0b64, 0x0ad6, 0x467d, \
+ { 0xaf, 0x62, 0x11, 0x57, 0xe7, 0xdc, 0x3c, 0x99 } \
+}
+struct IExtPackBase_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetName)(IExtPackBase *pThis, PRUnichar * *name);
+
+ nsresult (*GetDescription)(IExtPackBase *pThis, PRUnichar * *description);
+
+ nsresult (*GetVersion)(IExtPackBase *pThis, PRUnichar * *version);
+
+ nsresult (*GetRevision)(IExtPackBase *pThis, PRUint32 *revision);
+
+ nsresult (*GetVRDEModule)(IExtPackBase *pThis, PRUnichar * *VRDEModule);
+
+ nsresult (*GetPlugIns)(IExtPackBase *pThis, PRUint32 *plugInsSize, IExtPackPlugIn * **plugIns);
+
+ nsresult (*GetUsable)(IExtPackBase *pThis, PRBool *usable);
+
+ nsresult (*GetWhyUnusable)(IExtPackBase *pThis, PRUnichar * *whyUnusable);
+
+ nsresult (*GetShowLicense)(IExtPackBase *pThis, PRBool *showLicense);
+
+ nsresult (*GetLicense)(IExtPackBase *pThis, PRUnichar * *license);
+
+ nsresult (*QueryLicense)(
+ IExtPackBase *pThis,
+ PRUnichar * preferredLocale,
+ PRUnichar * preferredLanguage,
+ PRUnichar * format,
+ PRUnichar * * licenseText
+ );
+
+};
+
+struct IExtPackBase
+{
+ struct IExtPackBase_vtbl *vtbl;
+};
+/* End of struct IExtPackBase Declaration */
+
+
+/* Start of struct IExtPack Declaration */
+#define IEXTPACK_IID_STR "431685da-3618-4ebc-b038-833ba829b4b2"
+#define IEXTPACK_IID { \
+ 0x431685da, 0x3618, 0x4ebc, \
+ { 0xb0, 0x38, 0x83, 0x3b, 0xa8, 0x29, 0xb4, 0xb2 } \
+}
+struct IExtPack_vtbl
+{
+ struct IExtPackBase_vtbl iextpackbase;
+
+ nsresult (*QueryObject)(
+ IExtPack *pThis,
+ PRUnichar * objUuid,
+ nsISupports * * returnInterface
+ );
+
+};
+
+struct IExtPack
+{
+ struct IExtPack_vtbl *vtbl;
+};
+/* End of struct IExtPack Declaration */
+
+
+/* Start of struct IExtPackFile Declaration */
+#define IEXTPACKFILE_IID_STR "b6b49f55-efcc-4f08-b486-56e8d8afb10b"
+#define IEXTPACKFILE_IID { \
+ 0xb6b49f55, 0xefcc, 0x4f08, \
+ { 0xb4, 0x86, 0x56, 0xe8, 0xd8, 0xaf, 0xb1, 0x0b } \
+}
+struct IExtPackFile_vtbl
+{
+ struct IExtPackBase_vtbl iextpackbase;
+
+ nsresult (*GetFilePath)(IExtPackFile *pThis, PRUnichar * *filePath);
+
+ nsresult (*Install)(
+ IExtPackFile *pThis,
+ PRBool replace,
+ PRUnichar * displayInfo,
+ IProgress * * progess
+ );
+
+};
+
+struct IExtPackFile
+{
+ struct IExtPackFile_vtbl *vtbl;
+};
+/* End of struct IExtPackFile Declaration */
+
+
+/* Start of struct IExtPackManager Declaration */
+#define IEXTPACKMANAGER_IID_STR "3295e6ce-b051-47b2-9514-2c588bfe7554"
+#define IEXTPACKMANAGER_IID { \
+ 0x3295e6ce, 0xb051, 0x47b2, \
+ { 0x95, 0x14, 0x2c, 0x58, 0x8b, 0xfe, 0x75, 0x54 } \
+}
+struct IExtPackManager_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetInstalledExtPacks)(IExtPackManager *pThis, PRUint32 *installedExtPacksSize, IExtPack * **installedExtPacks);
+
+ nsresult (*Find)(
+ IExtPackManager *pThis,
+ PRUnichar * name,
+ IExtPack * * returnData
+ );
+
+ nsresult (*OpenExtPackFile)(
+ IExtPackManager *pThis,
+ PRUnichar * path,
+ IExtPackFile * * file
+ );
+
+ nsresult (*Uninstall)(
+ IExtPackManager *pThis,
+ PRUnichar * name,
+ PRBool forcedRemoval,
+ PRUnichar * displayInfo,
+ IProgress * * progess
+ );
+
+ nsresult (*Cleanup)(IExtPackManager *pThis );
+
+ nsresult (*QueryAllPlugInsForFrontend)(
+ IExtPackManager *pThis,
+ PRUnichar * frontendName,
+ PRUint32 *plugInModulesSize,
+ PRUnichar *** plugInModules
+ );
+
+ nsresult (*IsExtPackUsable)(
+ IExtPackManager *pThis,
+ PRUnichar * name,
+ PRBool * usable
+ );
+
+};
+
+struct IExtPackManager
+{
+ struct IExtPackManager_vtbl *vtbl;
+};
+/* End of struct IExtPackManager Declaration */
+
+
+/* Start of struct IBandwidthGroup Declaration */
+#define IBANDWIDTHGROUP_IID_STR "badea2d7-0261-4146-89f0-6a57cc34833d"
+#define IBANDWIDTHGROUP_IID { \
+ 0xbadea2d7, 0x0261, 0x4146, \
+ { 0x89, 0xf0, 0x6a, 0x57, 0xcc, 0x34, 0x83, 0x3d } \
+}
+struct IBandwidthGroup_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetName)(IBandwidthGroup *pThis, PRUnichar * *name);
+
+ nsresult (*GetType)(IBandwidthGroup *pThis, PRUint32 *type);
+
+ nsresult (*GetReference)(IBandwidthGroup *pThis, PRUint32 *reference);
+
+ nsresult (*GetMaxMbPerSec)(IBandwidthGroup *pThis, PRUint32 *maxMbPerSec);
+ nsresult (*SetMaxMbPerSec)(IBandwidthGroup *pThis, PRUint32 maxMbPerSec);
+
+};
+
+struct IBandwidthGroup
+{
+ struct IBandwidthGroup_vtbl *vtbl;
+};
+/* End of struct IBandwidthGroup Declaration */
+
+
+/* Start of struct IBandwidthControl Declaration */
+#define IBANDWIDTHCONTROL_IID_STR "e2eb3930-d2f4-4f87-be17-0707e30f019f"
+#define IBANDWIDTHCONTROL_IID { \
+ 0xe2eb3930, 0xd2f4, 0x4f87, \
+ { 0xbe, 0x17, 0x07, 0x07, 0xe3, 0x0f, 0x01, 0x9f } \
+}
+struct IBandwidthControl_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetNumGroups)(IBandwidthControl *pThis, PRUint32 *numGroups);
+
+ nsresult (*CreateBandwidthGroup)(
+ IBandwidthControl *pThis,
+ PRUnichar * name,
+ PRUint32 type,
+ PRUint32 maxMbPerSec
+ );
+
+ nsresult (*DeleteBandwidthGroup)(
+ IBandwidthControl *pThis,
+ PRUnichar * name
+ );
+
+ nsresult (*GetBandwidthGroup)(
+ IBandwidthControl *pThis,
+ PRUnichar * name,
+ IBandwidthGroup * * bandwidthGroup
+ );
+
+ nsresult (*GetAllBandwidthGroups)(
+ IBandwidthControl *pThis,
+ PRUint32 *bandwidthGroupsSize,
+ IBandwidthGroup *** bandwidthGroups
+ );
+
+};
+
+struct IBandwidthControl
+{
+ struct IBandwidthControl_vtbl *vtbl;
+};
+/* End of struct IBandwidthControl Declaration */
+
+
+/* Start of struct IVirtualBoxClient Declaration */
+#define IVIRTUALBOXCLIENT_IID_STR "5fe0bd48-1181-40d1-991f-3b02f269a823"
+#define IVIRTUALBOXCLIENT_IID { \
+ 0x5fe0bd48, 0x1181, 0x40d1, \
+ { 0x99, 0x1f, 0x3b, 0x02, 0xf2, 0x69, 0xa8, 0x23 } \
+}
+struct IVirtualBoxClient_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetVirtualBox)(IVirtualBoxClient *pThis, IVirtualBox * *virtualBox);
+
+ nsresult (*GetSession)(IVirtualBoxClient *pThis, ISession * *session);
+
+ nsresult (*GetEventSource)(IVirtualBoxClient *pThis, IEventSource * *eventSource);
+
+};
+
+struct IVirtualBoxClient
+{
+ struct IVirtualBoxClient_vtbl *vtbl;
+};
+/* End of struct IVirtualBoxClient Declaration */
+
+
+/* Start of struct IEventSource Declaration */
+#define IEVENTSOURCE_IID_STR "9b6e1aee-35f3-4f4d-b5bb-ed0ecefd8538"
+#define IEVENTSOURCE_IID { \
+ 0x9b6e1aee, 0x35f3, 0x4f4d, \
+ { 0xb5, 0xbb, 0xed, 0x0e, 0xce, 0xfd, 0x85, 0x38 } \
+}
+struct IEventSource_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*CreateListener)(
+ IEventSource *pThis,
+ IEventListener * * listener
+ );
+
+ nsresult (*CreateAggregator)(
+ IEventSource *pThis,
+ PRUint32 subordinatesSize,
+ IEventSource ** subordinates,
+ IEventSource * * result
+ );
+
+ nsresult (*RegisterListener)(
+ IEventSource *pThis,
+ IEventListener * listener,
+ PRUint32 interestingSize,
+ PRUint32* interesting,
+ PRBool active
+ );
+
+ nsresult (*UnregisterListener)(
+ IEventSource *pThis,
+ IEventListener * listener
+ );
+
+ nsresult (*FireEvent)(
+ IEventSource *pThis,
+ IEvent * event,
+ PRInt32 timeout,
+ PRBool * result
+ );
+
+ nsresult (*GetEvent)(
+ IEventSource *pThis,
+ IEventListener * listener,
+ PRInt32 timeout,
+ IEvent * * event
+ );
+
+ nsresult (*EventProcessed)(
+ IEventSource *pThis,
+ IEventListener * listener,
+ IEvent * event
+ );
+
+};
+
+struct IEventSource
+{
+ struct IEventSource_vtbl *vtbl;
+};
+/* End of struct IEventSource Declaration */
+
+
+/* Start of struct IEventListener Declaration */
+#define IEVENTLISTENER_IID_STR "67099191-32e7-4f6c-85ee-422304c71b90"
+#define IEVENTLISTENER_IID { \
+ 0x67099191, 0x32e7, 0x4f6c, \
+ { 0x85, 0xee, 0x42, 0x23, 0x04, 0xc7, 0x1b, 0x90 } \
+}
+struct IEventListener_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*HandleEvent)(
+ IEventListener *pThis,
+ IEvent * event
+ );
+
+};
+
+struct IEventListener
+{
+ struct IEventListener_vtbl *vtbl;
+};
+/* End of struct IEventListener Declaration */
+
+
+/* Start of struct IEvent Declaration */
+#define IEVENT_IID_STR "0ca2adba-8f30-401b-a8cd-fe31dbe839c0"
+#define IEVENT_IID { \
+ 0x0ca2adba, 0x8f30, 0x401b, \
+ { 0xa8, 0xcd, 0xfe, 0x31, 0xdb, 0xe8, 0x39, 0xc0 } \
+}
+struct IEvent_vtbl
+{
+ struct nsISupports_vtbl nsisupports;
+
+ nsresult (*GetType)(IEvent *pThis, PRUint32 *type);
+
+ nsresult (*GetSource)(IEvent *pThis, IEventSource * *source);
+
+ nsresult (*GetWaitable)(IEvent *pThis, PRBool *waitable);
+
+ nsresult (*SetProcessed)(IEvent *pThis );
+
+ nsresult (*WaitProcessed)(
+ IEvent *pThis,
+ PRInt32 timeout,
+ PRBool * result
+ );
+
+};
+
+struct IEvent
+{
+ struct IEvent_vtbl *vtbl;
+};
+/* End of struct IEvent Declaration */
+
+
+/* Start of struct IReusableEvent Declaration */
+#define IREUSABLEEVENT_IID_STR "69bfb134-80f6-4266-8e20-16371f68fa25"
+#define IREUSABLEEVENT_IID { \
+ 0x69bfb134, 0x80f6, 0x4266, \
+ { 0x8e, 0x20, 0x16, 0x37, 0x1f, 0x68, 0xfa, 0x25 } \
+}
+struct IReusableEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetGeneration)(IReusableEvent *pThis, PRUint32 *generation);
+
+ nsresult (*Reuse)(IReusableEvent *pThis );
+
+};
+
+struct IReusableEvent
+{
+ struct IReusableEvent_vtbl *vtbl;
+};
+/* End of struct IReusableEvent Declaration */
+
+
+/* Start of struct IMachineEvent Declaration */
+#define IMACHINEEVENT_IID_STR "92ed7b1a-0d96-40ed-ae46-a564d484325e"
+#define IMACHINEEVENT_IID { \
+ 0x92ed7b1a, 0x0d96, 0x40ed, \
+ { 0xae, 0x46, 0xa5, 0x64, 0xd4, 0x84, 0x32, 0x5e } \
+}
+struct IMachineEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetMachineId)(IMachineEvent *pThis, PRUnichar * *machineId);
+
+};
+
+struct IMachineEvent
+{
+ struct IMachineEvent_vtbl *vtbl;
+};
+/* End of struct IMachineEvent Declaration */
+
+
+/* Start of struct IMachineStateChangedEvent Declaration */
+#define IMACHINESTATECHANGEDEVENT_IID_STR "5748F794-48DF-438D-85EB-98FFD70D18C9"
+#define IMACHINESTATECHANGEDEVENT_IID { \
+ 0x5748F794, 0x48DF, 0x438D, \
+ { 0x85, 0xEB, 0x98, 0xFF, 0xD7, 0x0D, 0x18, 0xC9 } \
+}
+struct IMachineStateChangedEvent_vtbl
+{
+ struct IMachineEvent_vtbl imachineevent;
+
+ nsresult (*GetState)(IMachineStateChangedEvent *pThis, PRUint32 *state);
+
+};
+
+struct IMachineStateChangedEvent
+{
+ struct IMachineStateChangedEvent_vtbl *vtbl;
+};
+/* End of struct IMachineStateChangedEvent Declaration */
+
+
+/* Start of struct IMachineDataChangedEvent Declaration */
+#define IMACHINEDATACHANGEDEVENT_IID_STR "abe94809-2e88-4436-83d7-50f3e64d0503"
+#define IMACHINEDATACHANGEDEVENT_IID { \
+ 0xabe94809, 0x2e88, 0x4436, \
+ { 0x83, 0xd7, 0x50, 0xf3, 0xe6, 0x4d, 0x05, 0x03 } \
+}
+struct IMachineDataChangedEvent_vtbl
+{
+ struct IMachineEvent_vtbl imachineevent;
+
+ nsresult (*GetTemporary)(IMachineDataChangedEvent *pThis, PRBool *temporary);
+
+};
+
+struct IMachineDataChangedEvent
+{
+ struct IMachineDataChangedEvent_vtbl *vtbl;
+};
+/* End of struct IMachineDataChangedEvent Declaration */
+
+
+/* Start of struct IMediumRegisteredEvent Declaration */
+#define IMEDIUMREGISTEREDEVENT_IID_STR "53fac49a-b7f1-4a5a-a4ef-a11dd9c2a458"
+#define IMEDIUMREGISTEREDEVENT_IID { \
+ 0x53fac49a, 0xb7f1, 0x4a5a, \
+ { 0xa4, 0xef, 0xa1, 0x1d, 0xd9, 0xc2, 0xa4, 0x58 } \
+}
+struct IMediumRegisteredEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetMediumId)(IMediumRegisteredEvent *pThis, PRUnichar * *mediumId);
+
+ nsresult (*GetMediumType)(IMediumRegisteredEvent *pThis, PRUint32 *mediumType);
+
+ nsresult (*GetRegistered)(IMediumRegisteredEvent *pThis, PRBool *registered);
+
+};
+
+struct IMediumRegisteredEvent
+{
+ struct IMediumRegisteredEvent_vtbl *vtbl;
+};
+/* End of struct IMediumRegisteredEvent Declaration */
+
+
+/* Start of struct IMachineRegisteredEvent Declaration */
+#define IMACHINEREGISTEREDEVENT_IID_STR "c354a762-3ff2-4f2e-8f09-07382ee25088"
+#define IMACHINEREGISTEREDEVENT_IID { \
+ 0xc354a762, 0x3ff2, 0x4f2e, \
+ { 0x8f, 0x09, 0x07, 0x38, 0x2e, 0xe2, 0x50, 0x88 } \
+}
+struct IMachineRegisteredEvent_vtbl
+{
+ struct IMachineEvent_vtbl imachineevent;
+
+ nsresult (*GetRegistered)(IMachineRegisteredEvent *pThis, PRBool *registered);
+
+};
+
+struct IMachineRegisteredEvent
+{
+ struct IMachineRegisteredEvent_vtbl *vtbl;
+};
+/* End of struct IMachineRegisteredEvent Declaration */
+
+
+/* Start of struct ISessionStateChangedEvent Declaration */
+#define ISESSIONSTATECHANGEDEVENT_IID_STR "714a3eef-799a-4489-86cd-fe8e45b2ff8e"
+#define ISESSIONSTATECHANGEDEVENT_IID { \
+ 0x714a3eef, 0x799a, 0x4489, \
+ { 0x86, 0xcd, 0xfe, 0x8e, 0x45, 0xb2, 0xff, 0x8e } \
+}
+struct ISessionStateChangedEvent_vtbl
+{
+ struct IMachineEvent_vtbl imachineevent;
+
+ nsresult (*GetState)(ISessionStateChangedEvent *pThis, PRUint32 *state);
+
+};
+
+struct ISessionStateChangedEvent
+{
+ struct ISessionStateChangedEvent_vtbl *vtbl;
+};
+/* End of struct ISessionStateChangedEvent Declaration */
+
+
+/* Start of struct IGuestPropertyChangedEvent Declaration */
+#define IGUESTPROPERTYCHANGEDEVENT_IID_STR "3f63597a-26f1-4edb-8dd2-6bddd0912368"
+#define IGUESTPROPERTYCHANGEDEVENT_IID { \
+ 0x3f63597a, 0x26f1, 0x4edb, \
+ { 0x8d, 0xd2, 0x6b, 0xdd, 0xd0, 0x91, 0x23, 0x68 } \
+}
+struct IGuestPropertyChangedEvent_vtbl
+{
+ struct IMachineEvent_vtbl imachineevent;
+
+ nsresult (*GetName)(IGuestPropertyChangedEvent *pThis, PRUnichar * *name);
+
+ nsresult (*GetValue)(IGuestPropertyChangedEvent *pThis, PRUnichar * *value);
+
+ nsresult (*GetFlags)(IGuestPropertyChangedEvent *pThis, PRUnichar * *flags);
+
+};
+
+struct IGuestPropertyChangedEvent
+{
+ struct IGuestPropertyChangedEvent_vtbl *vtbl;
+};
+/* End of struct IGuestPropertyChangedEvent Declaration */
+
+
+/* Start of struct ISnapshotEvent Declaration */
+#define ISNAPSHOTEVENT_IID_STR "21637b0e-34b8-42d3-acfb-7e96daf77c22"
+#define ISNAPSHOTEVENT_IID { \
+ 0x21637b0e, 0x34b8, 0x42d3, \
+ { 0xac, 0xfb, 0x7e, 0x96, 0xda, 0xf7, 0x7c, 0x22 } \
+}
+struct ISnapshotEvent_vtbl
+{
+ struct IMachineEvent_vtbl imachineevent;
+
+ nsresult (*GetSnapshotId)(ISnapshotEvent *pThis, PRUnichar * *snapshotId);
+
+};
+
+struct ISnapshotEvent
+{
+ struct ISnapshotEvent_vtbl *vtbl;
+};
+/* End of struct ISnapshotEvent Declaration */
+
+
+/* Start of struct ISnapshotTakenEvent Declaration */
+#define ISNAPSHOTTAKENEVENT_IID_STR "d27c0b3d-6038-422c-b45e-6d4a0503d9f1"
+#define ISNAPSHOTTAKENEVENT_IID { \
+ 0xd27c0b3d, 0x6038, 0x422c, \
+ { 0xb4, 0x5e, 0x6d, 0x4a, 0x05, 0x03, 0xd9, 0xf1 } \
+}
+struct ISnapshotTakenEvent_vtbl
+{
+ struct ISnapshotEvent_vtbl isnapshotevent;
+
+};
+
+struct ISnapshotTakenEvent
+{
+ struct ISnapshotTakenEvent_vtbl *vtbl;
+};
+/* End of struct ISnapshotTakenEvent Declaration */
+
+
+/* Start of struct ISnapshotDeletedEvent Declaration */
+#define ISNAPSHOTDELETEDEVENT_IID_STR "c48f3401-4a9e-43f4-b7a7-54bd285e22f4"
+#define ISNAPSHOTDELETEDEVENT_IID { \
+ 0xc48f3401, 0x4a9e, 0x43f4, \
+ { 0xb7, 0xa7, 0x54, 0xbd, 0x28, 0x5e, 0x22, 0xf4 } \
+}
+struct ISnapshotDeletedEvent_vtbl
+{
+ struct ISnapshotEvent_vtbl isnapshotevent;
+
+};
+
+struct ISnapshotDeletedEvent
+{
+ struct ISnapshotDeletedEvent_vtbl *vtbl;
+};
+/* End of struct ISnapshotDeletedEvent Declaration */
+
+
+/* Start of struct ISnapshotChangedEvent Declaration */
+#define ISNAPSHOTCHANGEDEVENT_IID_STR "07541941-8079-447a-a33e-47a69c7980db"
+#define ISNAPSHOTCHANGEDEVENT_IID { \
+ 0x07541941, 0x8079, 0x447a, \
+ { 0xa3, 0x3e, 0x47, 0xa6, 0x9c, 0x79, 0x80, 0xdb } \
+}
+struct ISnapshotChangedEvent_vtbl
+{
+ struct ISnapshotEvent_vtbl isnapshotevent;
+
+};
+
+struct ISnapshotChangedEvent
+{
+ struct ISnapshotChangedEvent_vtbl *vtbl;
+};
+/* End of struct ISnapshotChangedEvent Declaration */
+
+
+/* Start of struct IMousePointerShapeChangedEvent Declaration */
+#define IMOUSEPOINTERSHAPECHANGEDEVENT_IID_STR "a6dcf6e8-416b-4181-8c4a-45ec95177aef"
+#define IMOUSEPOINTERSHAPECHANGEDEVENT_IID { \
+ 0xa6dcf6e8, 0x416b, 0x4181, \
+ { 0x8c, 0x4a, 0x45, 0xec, 0x95, 0x17, 0x7a, 0xef } \
+}
+struct IMousePointerShapeChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetVisible)(IMousePointerShapeChangedEvent *pThis, PRBool *visible);
+
+ nsresult (*GetAlpha)(IMousePointerShapeChangedEvent *pThis, PRBool *alpha);
+
+ nsresult (*GetXhot)(IMousePointerShapeChangedEvent *pThis, PRUint32 *xhot);
+
+ nsresult (*GetYhot)(IMousePointerShapeChangedEvent *pThis, PRUint32 *yhot);
+
+ nsresult (*GetWidth)(IMousePointerShapeChangedEvent *pThis, PRUint32 *width);
+
+ nsresult (*GetHeight)(IMousePointerShapeChangedEvent *pThis, PRUint32 *height);
+
+ nsresult (*GetShape)(IMousePointerShapeChangedEvent *pThis, PRUint32 *shapeSize, PRUint8 **shape);
+
+};
+
+struct IMousePointerShapeChangedEvent
+{
+ struct IMousePointerShapeChangedEvent_vtbl *vtbl;
+};
+/* End of struct IMousePointerShapeChangedEvent Declaration */
+
+
+/* Start of struct IMouseCapabilityChangedEvent Declaration */
+#define IMOUSECAPABILITYCHANGEDEVENT_IID_STR "d633ad48-820c-4207-b46c-6bd3596640d5"
+#define IMOUSECAPABILITYCHANGEDEVENT_IID { \
+ 0xd633ad48, 0x820c, 0x4207, \
+ { 0xb4, 0x6c, 0x6b, 0xd3, 0x59, 0x66, 0x40, 0xd5 } \
+}
+struct IMouseCapabilityChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetSupportsAbsolute)(IMouseCapabilityChangedEvent *pThis, PRBool *supportsAbsolute);
+
+ nsresult (*GetSupportsRelative)(IMouseCapabilityChangedEvent *pThis, PRBool *supportsRelative);
+
+ nsresult (*GetNeedsHostCursor)(IMouseCapabilityChangedEvent *pThis, PRBool *needsHostCursor);
+
+};
+
+struct IMouseCapabilityChangedEvent
+{
+ struct IMouseCapabilityChangedEvent_vtbl *vtbl;
+};
+/* End of struct IMouseCapabilityChangedEvent Declaration */
+
+
+/* Start of struct IKeyboardLedsChangedEvent Declaration */
+#define IKEYBOARDLEDSCHANGEDEVENT_IID_STR "6DDEF35E-4737-457B-99FC-BC52C851A44F"
+#define IKEYBOARDLEDSCHANGEDEVENT_IID { \
+ 0x6DDEF35E, 0x4737, 0x457B, \
+ { 0x99, 0xFC, 0xBC, 0x52, 0xC8, 0x51, 0xA4, 0x4F } \
+}
+struct IKeyboardLedsChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetNumLock)(IKeyboardLedsChangedEvent *pThis, PRBool *numLock);
+
+ nsresult (*GetCapsLock)(IKeyboardLedsChangedEvent *pThis, PRBool *capsLock);
+
+ nsresult (*GetScrollLock)(IKeyboardLedsChangedEvent *pThis, PRBool *scrollLock);
+
+};
+
+struct IKeyboardLedsChangedEvent
+{
+ struct IKeyboardLedsChangedEvent_vtbl *vtbl;
+};
+/* End of struct IKeyboardLedsChangedEvent Declaration */
+
+
+/* Start of struct IStateChangedEvent Declaration */
+#define ISTATECHANGEDEVENT_IID_STR "4376693C-CF37-453B-9289-3B0F521CAF27"
+#define ISTATECHANGEDEVENT_IID { \
+ 0x4376693C, 0xCF37, 0x453B, \
+ { 0x92, 0x89, 0x3B, 0x0F, 0x52, 0x1C, 0xAF, 0x27 } \
+}
+struct IStateChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetState)(IStateChangedEvent *pThis, PRUint32 *state);
+
+};
+
+struct IStateChangedEvent
+{
+ struct IStateChangedEvent_vtbl *vtbl;
+};
+/* End of struct IStateChangedEvent Declaration */
+
+
+/* Start of struct IAdditionsStateChangedEvent Declaration */
+#define IADDITIONSSTATECHANGEDEVENT_IID_STR "D70F7915-DA7C-44C8-A7AC-9F173490446A"
+#define IADDITIONSSTATECHANGEDEVENT_IID { \
+ 0xD70F7915, 0xDA7C, 0x44C8, \
+ { 0xA7, 0xAC, 0x9F, 0x17, 0x34, 0x90, 0x44, 0x6A } \
+}
+struct IAdditionsStateChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+};
+
+struct IAdditionsStateChangedEvent
+{
+ struct IAdditionsStateChangedEvent_vtbl *vtbl;
+};
+/* End of struct IAdditionsStateChangedEvent Declaration */
+
+
+/* Start of struct INetworkAdapterChangedEvent Declaration */
+#define INETWORKADAPTERCHANGEDEVENT_IID_STR "08889892-1EC6-4883-801D-77F56CFD0103"
+#define INETWORKADAPTERCHANGEDEVENT_IID { \
+ 0x08889892, 0x1EC6, 0x4883, \
+ { 0x80, 0x1D, 0x77, 0xF5, 0x6C, 0xFD, 0x01, 0x03 } \
+}
+struct INetworkAdapterChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetNetworkAdapter)(INetworkAdapterChangedEvent *pThis, INetworkAdapter * *networkAdapter);
+
+};
+
+struct INetworkAdapterChangedEvent
+{
+ struct INetworkAdapterChangedEvent_vtbl *vtbl;
+};
+/* End of struct INetworkAdapterChangedEvent Declaration */
+
+
+/* Start of struct ISerialPortChangedEvent Declaration */
+#define ISERIALPORTCHANGEDEVENT_IID_STR "3BA329DC-659C-488B-835C-4ECA7AE71C6C"
+#define ISERIALPORTCHANGEDEVENT_IID { \
+ 0x3BA329DC, 0x659C, 0x488B, \
+ { 0x83, 0x5C, 0x4E, 0xCA, 0x7A, 0xE7, 0x1C, 0x6C } \
+}
+struct ISerialPortChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetSerialPort)(ISerialPortChangedEvent *pThis, ISerialPort * *serialPort);
+
+};
+
+struct ISerialPortChangedEvent
+{
+ struct ISerialPortChangedEvent_vtbl *vtbl;
+};
+/* End of struct ISerialPortChangedEvent Declaration */
+
+
+/* Start of struct IParallelPortChangedEvent Declaration */
+#define IPARALLELPORTCHANGEDEVENT_IID_STR "813C99FC-9849-4F47-813E-24A75DC85615"
+#define IPARALLELPORTCHANGEDEVENT_IID { \
+ 0x813C99FC, 0x9849, 0x4F47, \
+ { 0x81, 0x3E, 0x24, 0xA7, 0x5D, 0xC8, 0x56, 0x15 } \
+}
+struct IParallelPortChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetParallelPort)(IParallelPortChangedEvent *pThis, IParallelPort * *parallelPort);
+
+};
+
+struct IParallelPortChangedEvent
+{
+ struct IParallelPortChangedEvent_vtbl *vtbl;
+};
+/* End of struct IParallelPortChangedEvent Declaration */
+
+
+/* Start of struct IStorageControllerChangedEvent Declaration */
+#define ISTORAGECONTROLLERCHANGEDEVENT_IID_STR "715212BF-DA59-426E-8230-3831FAA52C56"
+#define ISTORAGECONTROLLERCHANGEDEVENT_IID { \
+ 0x715212BF, 0xDA59, 0x426E, \
+ { 0x82, 0x30, 0x38, 0x31, 0xFA, 0xA5, 0x2C, 0x56 } \
+}
+struct IStorageControllerChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+};
+
+struct IStorageControllerChangedEvent
+{
+ struct IStorageControllerChangedEvent_vtbl *vtbl;
+};
+/* End of struct IStorageControllerChangedEvent Declaration */
+
+
+/* Start of struct IMediumChangedEvent Declaration */
+#define IMEDIUMCHANGEDEVENT_IID_STR "0FE2DA40-5637-472A-9736-72019EABD7DE"
+#define IMEDIUMCHANGEDEVENT_IID { \
+ 0x0FE2DA40, 0x5637, 0x472A, \
+ { 0x97, 0x36, 0x72, 0x01, 0x9E, 0xAB, 0xD7, 0xDE } \
+}
+struct IMediumChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetMediumAttachment)(IMediumChangedEvent *pThis, IMediumAttachment * *mediumAttachment);
+
+};
+
+struct IMediumChangedEvent
+{
+ struct IMediumChangedEvent_vtbl *vtbl;
+};
+/* End of struct IMediumChangedEvent Declaration */
+
+
+/* Start of struct ICPUChangedEvent Declaration */
+#define ICPUCHANGEDEVENT_IID_STR "D0F0BECC-EE17-4D17-A8CC-383B0EB55E9D"
+#define ICPUCHANGEDEVENT_IID { \
+ 0xD0F0BECC, 0xEE17, 0x4D17, \
+ { 0xA8, 0xCC, 0x38, 0x3B, 0x0E, 0xB5, 0x5E, 0x9D } \
+}
+struct ICPUChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetCpu)(ICPUChangedEvent *pThis, PRUint32 *cpu);
+
+ nsresult (*GetAdd)(ICPUChangedEvent *pThis, PRBool *add);
+
+};
+
+struct ICPUChangedEvent
+{
+ struct ICPUChangedEvent_vtbl *vtbl;
+};
+/* End of struct ICPUChangedEvent Declaration */
+
+
+/* Start of struct ICPUExecutionCapChangedEvent Declaration */
+#define ICPUEXECUTIONCAPCHANGEDEVENT_IID_STR "dfa7e4f5-b4a4-44ce-85a8-127ac5eb59dc"
+#define ICPUEXECUTIONCAPCHANGEDEVENT_IID { \
+ 0xdfa7e4f5, 0xb4a4, 0x44ce, \
+ { 0x85, 0xa8, 0x12, 0x7a, 0xc5, 0xeb, 0x59, 0xdc } \
+}
+struct ICPUExecutionCapChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetExecutionCap)(ICPUExecutionCapChangedEvent *pThis, PRUint32 *executionCap);
+
+};
+
+struct ICPUExecutionCapChangedEvent
+{
+ struct ICPUExecutionCapChangedEvent_vtbl *vtbl;
+};
+/* End of struct ICPUExecutionCapChangedEvent Declaration */
+
+
+/* Start of struct IGuestKeyboardEvent Declaration */
+#define IGUESTKEYBOARDEVENT_IID_STR "88394258-7006-40d4-b339-472ee3801844"
+#define IGUESTKEYBOARDEVENT_IID { \
+ 0x88394258, 0x7006, 0x40d4, \
+ { 0xb3, 0x39, 0x47, 0x2e, 0xe3, 0x80, 0x18, 0x44 } \
+}
+struct IGuestKeyboardEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetScancodes)(IGuestKeyboardEvent *pThis, PRUint32 *scancodesSize, PRInt32 **scancodes);
+
+};
+
+struct IGuestKeyboardEvent
+{
+ struct IGuestKeyboardEvent_vtbl *vtbl;
+};
+/* End of struct IGuestKeyboardEvent Declaration */
+
+
+/* Start of struct IGuestMouseEvent Declaration */
+#define IGUESTMOUSEEVENT_IID_STR "1f85d35c-c524-40ff-8e98-307000df0992"
+#define IGUESTMOUSEEVENT_IID { \
+ 0x1f85d35c, 0xc524, 0x40ff, \
+ { 0x8e, 0x98, 0x30, 0x70, 0x00, 0xdf, 0x09, 0x92 } \
+}
+struct IGuestMouseEvent_vtbl
+{
+ struct IReusableEvent_vtbl ireusableevent;
+
+ nsresult (*GetAbsolute)(IGuestMouseEvent *pThis, PRBool *absolute);
+
+ nsresult (*GetX)(IGuestMouseEvent *pThis, PRInt32 *x);
+
+ nsresult (*GetY)(IGuestMouseEvent *pThis, PRInt32 *y);
+
+ nsresult (*GetZ)(IGuestMouseEvent *pThis, PRInt32 *z);
+
+ nsresult (*GetW)(IGuestMouseEvent *pThis, PRInt32 *w);
+
+ nsresult (*GetButtons)(IGuestMouseEvent *pThis, PRInt32 *buttons);
+
+};
+
+struct IGuestMouseEvent
+{
+ struct IGuestMouseEvent_vtbl *vtbl;
+};
+/* End of struct IGuestMouseEvent Declaration */
+
+
+/* Start of struct IVRDEServerChangedEvent Declaration */
+#define IVRDESERVERCHANGEDEVENT_IID_STR "a06fd66a-3188-4c8c-8756-1395e8cb691c"
+#define IVRDESERVERCHANGEDEVENT_IID { \
+ 0xa06fd66a, 0x3188, 0x4c8c, \
+ { 0x87, 0x56, 0x13, 0x95, 0xe8, 0xcb, 0x69, 0x1c } \
+}
+struct IVRDEServerChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+};
+
+struct IVRDEServerChangedEvent
+{
+ struct IVRDEServerChangedEvent_vtbl *vtbl;
+};
+/* End of struct IVRDEServerChangedEvent Declaration */
+
+
+/* Start of struct IVRDEServerInfoChangedEvent Declaration */
+#define IVRDESERVERINFOCHANGEDEVENT_IID_STR "dd6a1080-e1b7-4339-a549-f0878115596e"
+#define IVRDESERVERINFOCHANGEDEVENT_IID { \
+ 0xdd6a1080, 0xe1b7, 0x4339, \
+ { 0xa5, 0x49, 0xf0, 0x87, 0x81, 0x15, 0x59, 0x6e } \
+}
+struct IVRDEServerInfoChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+};
+
+struct IVRDEServerInfoChangedEvent
+{
+ struct IVRDEServerInfoChangedEvent_vtbl *vtbl;
+};
+/* End of struct IVRDEServerInfoChangedEvent Declaration */
+
+
+/* Start of struct IUSBControllerChangedEvent Declaration */
+#define IUSBCONTROLLERCHANGEDEVENT_IID_STR "93BADC0C-61D9-4940-A084-E6BB29AF3D83"
+#define IUSBCONTROLLERCHANGEDEVENT_IID { \
+ 0x93BADC0C, 0x61D9, 0x4940, \
+ { 0xA0, 0x84, 0xE6, 0xBB, 0x29, 0xAF, 0x3D, 0x83 } \
+}
+struct IUSBControllerChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+};
+
+struct IUSBControllerChangedEvent
+{
+ struct IUSBControllerChangedEvent_vtbl *vtbl;
+};
+/* End of struct IUSBControllerChangedEvent Declaration */
+
+
+/* Start of struct IUSBDeviceStateChangedEvent Declaration */
+#define IUSBDEVICESTATECHANGEDEVENT_IID_STR "806da61b-6679-422a-b629-51b06b0c6d93"
+#define IUSBDEVICESTATECHANGEDEVENT_IID { \
+ 0x806da61b, 0x6679, 0x422a, \
+ { 0xb6, 0x29, 0x51, 0xb0, 0x6b, 0x0c, 0x6d, 0x93 } \
+}
+struct IUSBDeviceStateChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetDevice)(IUSBDeviceStateChangedEvent *pThis, IUSBDevice * *device);
+
+ nsresult (*GetAttached)(IUSBDeviceStateChangedEvent *pThis, PRBool *attached);
+
+ nsresult (*GetError)(IUSBDeviceStateChangedEvent *pThis, IVirtualBoxErrorInfo * *error);
+
+};
+
+struct IUSBDeviceStateChangedEvent
+{
+ struct IUSBDeviceStateChangedEvent_vtbl *vtbl;
+};
+/* End of struct IUSBDeviceStateChangedEvent Declaration */
+
+
+/* Start of struct ISharedFolderChangedEvent Declaration */
+#define ISHAREDFOLDERCHANGEDEVENT_IID_STR "B66349B5-3534-4239-B2DE-8E1535D94C0B"
+#define ISHAREDFOLDERCHANGEDEVENT_IID { \
+ 0xB66349B5, 0x3534, 0x4239, \
+ { 0xB2, 0xDE, 0x8E, 0x15, 0x35, 0xD9, 0x4C, 0x0B } \
+}
+struct ISharedFolderChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetScope)(ISharedFolderChangedEvent *pThis, PRUint32 *scope);
+
+};
+
+struct ISharedFolderChangedEvent
+{
+ struct ISharedFolderChangedEvent_vtbl *vtbl;
+};
+/* End of struct ISharedFolderChangedEvent Declaration */
+
+
+/* Start of struct IRuntimeErrorEvent Declaration */
+#define IRUNTIMEERROREVENT_IID_STR "883DD18B-0721-4CDE-867C-1A82ABAF914C"
+#define IRUNTIMEERROREVENT_IID { \
+ 0x883DD18B, 0x0721, 0x4CDE, \
+ { 0x86, 0x7C, 0x1A, 0x82, 0xAB, 0xAF, 0x91, 0x4C } \
+}
+struct IRuntimeErrorEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetFatal)(IRuntimeErrorEvent *pThis, PRBool *fatal);
+
+ nsresult (*GetId)(IRuntimeErrorEvent *pThis, PRUnichar * *id);
+
+ nsresult (*GetMessage)(IRuntimeErrorEvent *pThis, PRUnichar * *message);
+
+};
+
+struct IRuntimeErrorEvent
+{
+ struct IRuntimeErrorEvent_vtbl *vtbl;
+};
+/* End of struct IRuntimeErrorEvent Declaration */
+
+
+/* Start of struct IEventSourceChangedEvent Declaration */
+#define IEVENTSOURCECHANGEDEVENT_IID_STR "e7932cb8-f6d4-4ab6-9cbf-558eb8959a6a"
+#define IEVENTSOURCECHANGEDEVENT_IID { \
+ 0xe7932cb8, 0xf6d4, 0x4ab6, \
+ { 0x9c, 0xbf, 0x55, 0x8e, 0xb8, 0x95, 0x9a, 0x6a } \
+}
+struct IEventSourceChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetListener)(IEventSourceChangedEvent *pThis, IEventListener * *listener);
+
+ nsresult (*GetAdd)(IEventSourceChangedEvent *pThis, PRBool *add);
+
+};
+
+struct IEventSourceChangedEvent
+{
+ struct IEventSourceChangedEvent_vtbl *vtbl;
+};
+/* End of struct IEventSourceChangedEvent Declaration */
+
+
+/* Start of struct IExtraDataChangedEvent Declaration */
+#define IEXTRADATACHANGEDEVENT_IID_STR "024F00CE-6E0B-492A-A8D0-968472A94DC7"
+#define IEXTRADATACHANGEDEVENT_IID { \
+ 0x024F00CE, 0x6E0B, 0x492A, \
+ { 0xA8, 0xD0, 0x96, 0x84, 0x72, 0xA9, 0x4D, 0xC7 } \
+}
+struct IExtraDataChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetMachineId)(IExtraDataChangedEvent *pThis, PRUnichar * *machineId);
+
+ nsresult (*GetKey)(IExtraDataChangedEvent *pThis, PRUnichar * *key);
+
+ nsresult (*GetValue)(IExtraDataChangedEvent *pThis, PRUnichar * *value);
+
+};
+
+struct IExtraDataChangedEvent
+{
+ struct IExtraDataChangedEvent_vtbl *vtbl;
+};
+/* End of struct IExtraDataChangedEvent Declaration */
+
+
+/* Start of struct IVetoEvent Declaration */
+#define IVETOEVENT_IID_STR "9a1a4130-69fe-472f-ac10-c6fa25d75007"
+#define IVETOEVENT_IID { \
+ 0x9a1a4130, 0x69fe, 0x472f, \
+ { 0xac, 0x10, 0xc6, 0xfa, 0x25, 0xd7, 0x50, 0x07 } \
+}
+struct IVetoEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*AddVeto)(
+ IVetoEvent *pThis,
+ PRUnichar * reason
+ );
+
+ nsresult (*IsVetoed)(
+ IVetoEvent *pThis,
+ PRBool * result
+ );
+
+ nsresult (*GetVetos)(
+ IVetoEvent *pThis,
+ PRUint32 *resultSize,
+ PRUnichar *** result
+ );
+
+};
+
+struct IVetoEvent
+{
+ struct IVetoEvent_vtbl *vtbl;
+};
+/* End of struct IVetoEvent Declaration */
+
+
+/* Start of struct IExtraDataCanChangeEvent Declaration */
+#define IEXTRADATACANCHANGEEVENT_IID_STR "245d88bd-800a-40f8-87a6-170d02249a55"
+#define IEXTRADATACANCHANGEEVENT_IID { \
+ 0x245d88bd, 0x800a, 0x40f8, \
+ { 0x87, 0xa6, 0x17, 0x0d, 0x02, 0x24, 0x9a, 0x55 } \
+}
+struct IExtraDataCanChangeEvent_vtbl
+{
+ struct IVetoEvent_vtbl ivetoevent;
+
+ nsresult (*GetMachineId)(IExtraDataCanChangeEvent *pThis, PRUnichar * *machineId);
+
+ nsresult (*GetKey)(IExtraDataCanChangeEvent *pThis, PRUnichar * *key);
+
+ nsresult (*GetValue)(IExtraDataCanChangeEvent *pThis, PRUnichar * *value);
+
+};
+
+struct IExtraDataCanChangeEvent
+{
+ struct IExtraDataCanChangeEvent_vtbl *vtbl;
+};
+/* End of struct IExtraDataCanChangeEvent Declaration */
+
+
+/* Start of struct ICanShowWindowEvent Declaration */
+#define ICANSHOWWINDOWEVENT_IID_STR "adf292b0-92c9-4a77-9d35-e058b39fe0b9"
+#define ICANSHOWWINDOWEVENT_IID { \
+ 0xadf292b0, 0x92c9, 0x4a77, \
+ { 0x9d, 0x35, 0xe0, 0x58, 0xb3, 0x9f, 0xe0, 0xb9 } \
+}
+struct ICanShowWindowEvent_vtbl
+{
+ struct IVetoEvent_vtbl ivetoevent;
+
+};
+
+struct ICanShowWindowEvent
+{
+ struct ICanShowWindowEvent_vtbl *vtbl;
+};
+/* End of struct ICanShowWindowEvent Declaration */
+
+
+/* Start of struct IShowWindowEvent Declaration */
+#define ISHOWWINDOWEVENT_IID_STR "B0A0904D-2F05-4D28-855F-488F96BAD2B2"
+#define ISHOWWINDOWEVENT_IID { \
+ 0xB0A0904D, 0x2F05, 0x4D28, \
+ { 0x85, 0x5F, 0x48, 0x8F, 0x96, 0xBA, 0xD2, 0xB2 } \
+}
+struct IShowWindowEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetWinId)(IShowWindowEvent *pThis, PRInt64 *winId);
+ nsresult (*SetWinId)(IShowWindowEvent *pThis, PRInt64 winId);
+
+};
+
+struct IShowWindowEvent
+{
+ struct IShowWindowEvent_vtbl *vtbl;
+};
+/* End of struct IShowWindowEvent Declaration */
+
+
+/* Start of struct INATRedirectEvent Declaration */
+#define INATREDIRECTEVENT_IID_STR "57DE97D7-3CBB-42A0-888F-610D5832D16B"
+#define INATREDIRECTEVENT_IID { \
+ 0x57DE97D7, 0x3CBB, 0x42A0, \
+ { 0x88, 0x8F, 0x61, 0x0D, 0x58, 0x32, 0xD1, 0x6B } \
+}
+struct INATRedirectEvent_vtbl
+{
+ struct IMachineEvent_vtbl imachineevent;
+
+ nsresult (*GetSlot)(INATRedirectEvent *pThis, PRUint32 *slot);
+
+ nsresult (*GetRemove)(INATRedirectEvent *pThis, PRBool *remove);
+
+ nsresult (*GetName)(INATRedirectEvent *pThis, PRUnichar * *name);
+
+ nsresult (*GetProto)(INATRedirectEvent *pThis, PRUint32 *proto);
+
+ nsresult (*GetHostIp)(INATRedirectEvent *pThis, PRUnichar * *hostIp);
+
+ nsresult (*GetHostPort)(INATRedirectEvent *pThis, PRInt32 *hostPort);
+
+ nsresult (*GetGuestIp)(INATRedirectEvent *pThis, PRUnichar * *guestIp);
+
+ nsresult (*GetGuestPort)(INATRedirectEvent *pThis, PRInt32 *guestPort);
+
+};
+
+struct INATRedirectEvent
+{
+ struct INATRedirectEvent_vtbl *vtbl;
+};
+/* End of struct INATRedirectEvent Declaration */
+
+
+/* Start of struct IHostPciDevicePlugEvent Declaration */
+#define IHOSTPCIDEVICEPLUGEVENT_IID_STR "9cebfc27-c579-4965-8eb7-d31794cd7dcf"
+#define IHOSTPCIDEVICEPLUGEVENT_IID { \
+ 0x9cebfc27, 0xc579, 0x4965, \
+ { 0x8e, 0xb7, 0xd3, 0x17, 0x94, 0xcd, 0x7d, 0xcf } \
+}
+struct IHostPciDevicePlugEvent_vtbl
+{
+ struct IMachineEvent_vtbl imachineevent;
+
+ nsresult (*GetPlugged)(IHostPciDevicePlugEvent *pThis, PRBool *plugged);
+
+ nsresult (*GetSuccess)(IHostPciDevicePlugEvent *pThis, PRBool *success);
+
+ nsresult (*GetAttachment)(IHostPciDevicePlugEvent *pThis, IPciDeviceAttachment * *attachment);
+
+ nsresult (*GetMessage)(IHostPciDevicePlugEvent *pThis, PRUnichar * *message);
+
+};
+
+struct IHostPciDevicePlugEvent
+{
+ struct IHostPciDevicePlugEvent_vtbl *vtbl;
+};
+/* End of struct IHostPciDevicePlugEvent Declaration */
+
+
+/* Start of struct IVBoxSVCAvailabilityChangedEvent Declaration */
+#define IVBOXSVCAVAILABILITYCHANGEDEVENT_IID_STR "97c78fcd-d4fc-485f-8613-5af88bfcfcdc"
+#define IVBOXSVCAVAILABILITYCHANGEDEVENT_IID { \
+ 0x97c78fcd, 0xd4fc, 0x485f, \
+ { 0x86, 0x13, 0x5a, 0xf8, 0x8b, 0xfc, 0xfc, 0xdc } \
+}
+struct IVBoxSVCAvailabilityChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetAvailable)(IVBoxSVCAvailabilityChangedEvent *pThis, PRBool *available);
+
+};
+
+struct IVBoxSVCAvailabilityChangedEvent
+{
+ struct IVBoxSVCAvailabilityChangedEvent_vtbl *vtbl;
+};
+/* End of struct IVBoxSVCAvailabilityChangedEvent Declaration */
+
+
+/* Start of struct IBandwidthGroupChangedEvent Declaration */
+#define IBANDWIDTHGROUPCHANGEDEVENT_IID_STR "334df94a-7556-4cbc-8c04-043096b02d82"
+#define IBANDWIDTHGROUPCHANGEDEVENT_IID { \
+ 0x334df94a, 0x7556, 0x4cbc, \
+ { 0x8c, 0x04, 0x04, 0x30, 0x96, 0xb0, 0x2d, 0x82 } \
+}
+struct IBandwidthGroupChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetBandwidthGroup)(IBandwidthGroupChangedEvent *pThis, IBandwidthGroup * *bandwidthGroup);
+
+};
+
+struct IBandwidthGroupChangedEvent
+{
+ struct IBandwidthGroupChangedEvent_vtbl *vtbl;
+};
+/* End of struct IBandwidthGroupChangedEvent Declaration */
+
+
+/* Start of struct IGuestMonitorChangedEvent Declaration */
+#define IGUESTMONITORCHANGEDEVENT_IID_STR "0f7b8a22-c71f-4a36-8e5f-a77d01d76090"
+#define IGUESTMONITORCHANGEDEVENT_IID { \
+ 0x0f7b8a22, 0xc71f, 0x4a36, \
+ { 0x8e, 0x5f, 0xa7, 0x7d, 0x01, 0xd7, 0x60, 0x90 } \
+}
+struct IGuestMonitorChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetChangeType)(IGuestMonitorChangedEvent *pThis, PRUint32 *changeType);
+
+ nsresult (*GetScreenId)(IGuestMonitorChangedEvent *pThis, PRUint32 *screenId);
+
+ nsresult (*GetOriginX)(IGuestMonitorChangedEvent *pThis, PRUint32 *originX);
+
+ nsresult (*GetOriginY)(IGuestMonitorChangedEvent *pThis, PRUint32 *originY);
+
+ nsresult (*GetWidth)(IGuestMonitorChangedEvent *pThis, PRUint32 *width);
+
+ nsresult (*GetHeight)(IGuestMonitorChangedEvent *pThis, PRUint32 *height);
+
+};
+
+struct IGuestMonitorChangedEvent
+{
+ struct IGuestMonitorChangedEvent_vtbl *vtbl;
+};
+/* End of struct IGuestMonitorChangedEvent Declaration */
+
+
+/* Start of struct IStorageDeviceChangedEvent Declaration */
+#define ISTORAGEDEVICECHANGEDEVENT_IID_STR "8a5c2dce-e341-49d4-afce-c95979f7d70c"
+#define ISTORAGEDEVICECHANGEDEVENT_IID { \
+ 0x8a5c2dce, 0xe341, 0x49d4, \
+ { 0xaf, 0xce, 0xc9, 0x59, 0x79, 0xf7, 0xd7, 0x0c } \
+}
+struct IStorageDeviceChangedEvent_vtbl
+{
+ struct IEvent_vtbl ievent;
+
+ nsresult (*GetStorageDevice)(IStorageDeviceChangedEvent *pThis, IMediumAttachment * *storageDevice);
+
+ nsresult (*GetRemoved)(IStorageDeviceChangedEvent *pThis, PRBool *removed);
+
+};
+
+struct IStorageDeviceChangedEvent
+{
+ struct IStorageDeviceChangedEvent_vtbl *vtbl;
+};
+/* End of struct IStorageDeviceChangedEvent Declaration */
+
+
+
+#define NS_VIRTUALBOX_CID { \
+ 0xB1A7A4F2, 0x47B9, 0x4A1E, \
+ { 0x82, 0xB2, 0x07, 0xCC, 0xD5, 0x32, 0x3C, 0x3F } \
+}
+#define NS_VIRTUALBOX_CONTRACTID "@virtualbox.org/VirtualBox;1"
+/* for compatibility with Win32 */
+#define CLSID_VirtualBox (nsCID) NS_VIRTUALBOX_CID
+
+
+
+#define NS_VIRTUALBOXCLIENT_CID { \
+ 0xdd3fc71d, 0x26c0, 0x4fe1, \
+ { 0xbf, 0x6f, 0x67, 0xf6, 0x33, 0x26, 0x5b, 0xba } \
+}
+#define NS_VIRTUALBOXCLIENT_CONTRACTID "@virtualbox.org/VirtualBoxClient;1"
+/* for compatibility with Win32 */
+#define CLSID_VirtualBoxClient (nsCID) NS_VIRTUALBOXCLIENT_CID
+
+
+
+#define NS_SESSION_CID { \
+ 0x3C02F46D, 0xC9D2, 0x4F11, \
+ { 0xA3, 0x84, 0x53, 0xF0, 0xCF, 0x91, 0x72, 0x14 } \
+}
+#define NS_SESSION_CONTRACTID "@virtualbox.org/Session;1"
+/* for compatibility with Win32 */
+#define CLSID_Session (nsCID) NS_SESSION_CID
+
+
+
+#endif /* !__cplusplus */
+
+#ifdef IN_VBOXXPCOMC
+# define VBOXXPCOMC_DECL(type) PR_EXPORT(type)
+#else
+# define VBOXXPCOMC_DECL(type) PR_IMPORT(type)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Function table for dynamic linking.
+ * Use VBoxGetFunctions() to obtain the pointer to it.
+ */
+typedef struct VBOXXPCOMC
+{
+ /** The size of the structure. */
+ unsigned cb;
+ /** The structure version. */
+ unsigned uVersion;
+
+ unsigned int (*pfnGetVersion)(void);
+
+ void (*pfnComInitialize)(const char *pszVirtualBoxIID,
+ IVirtualBox **ppVirtualBox,
+ const char *pszSessionIID,
+ ISession **ppSession);
+ void (*pfnComUninitialize)(void);
+
+ void (*pfnComUnallocMem)(void *pv);
+ void (*pfnUtf16Free)(PRUnichar *pwszString);
+ void (*pfnUtf8Free)(char *pszString);
+
+ int (*pfnUtf16ToUtf8)(const PRUnichar *pwszString, char **ppszString);
+ int (*pfnUtf8ToUtf16)(const char *pszString, PRUnichar **ppwszString);
+
+ void (*pfnGetEventQueue)(nsIEventQueue **eventQueue);
+
+ /** Tail version, same as uVersion. */
+ unsigned uEndVersion;
+} VBOXXPCOMC;
+/** Pointer to a const VBoxXPCOMC function table. */
+typedef VBOXXPCOMC const *PCVBOXXPCOM;
+
+/** The current interface version.
+ * For use with VBoxGetXPCOMCFunctions and to be found in
+ * VBOXXPCOMC::uVersion. */
+#define VBOX_XPCOMC_VERSION 0x00020000U
+
+VBOXXPCOMC_DECL(PCVBOXXPCOM) VBoxGetXPCOMCFunctions(unsigned uVersion);
+/** Typedef for VBoxGetXPCOMCFunctions. */
+typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
+
+/** The symbol name of VBoxGetXPCOMCFunctions. */
+#if defined(__OS2__)
+# define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME "_VBoxGetXPCOMCFunctions"
+#else
+# define VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME "VBoxGetXPCOMCFunctions"
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !___VirtualBox_CXPCOM_h */
diff --git a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.h b/src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in
index 0f42a4bc0..7a1e9cc15 100644
--- a/src/VBox/Main/cbinding/VBoxXPCOMCGlue.h
+++ b/src/VBox/Main/cbinding/VBoxXPCOMCGlue.h.in
@@ -1,4 +1,4 @@
-/* $Revision: 75929 $ */
+/* $Revision: 75934 $ */
/** @file VBoxXPCOMCGlue.h
* Glue for dynamically linking with VBoxXPCOMC.
*/
@@ -31,7 +31,7 @@
#ifndef ___VBoxXPCOMC_cglue_h
#define ___VBoxXPCOMC_cglue_h
-#include "VBoxCAPI_v4_1.h"
+#include "VBoxCAPI_v@VBOX_API_VERSION@.h"
#ifdef __cplusplus
extern "C" {
diff --git a/src/VBox/Main/cbinding/xpcidl.xsl b/src/VBox/Main/cbinding/xpcidl.xsl
index d4019c6f5..c1220c700 100644
--- a/src/VBox/Main/cbinding/xpcidl.xsl
+++ b/src/VBox/Main/cbinding/xpcidl.xsl
@@ -5,15 +5,15 @@
* A template to generate a XPCOM IDL compatible interface definition file
* from the generic interface definition expressed in XML.
- Copyright (C) 2008-2012 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2008-2012 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
@@ -1270,23 +1270,22 @@ typedef PCVBOXXPCOM (*PFNVBOXGETXPCOMCFUNCTIONS)(unsigned uVersion);
<xsl:text>);&#x0A;</xsl:text>
<!-- setter -->
<xsl:if test="not(@readonly='yes')">
- <xsl:text> nsresult set</xsl:text>
+ <xsl:text> nsresult (*Set</xsl:text>
<xsl:call-template name="capitalize">
<xsl:with-param name="str" select="@name"/>
</xsl:call-template>
- <xsl:text> (&#x0A;</xsl:text>
+ <xsl:text>)(</xsl:text>
+ <xsl:value-of select="../@name" />
+ <xsl:text> *pThis, </xsl:text>
<!-- array size -->
- <xsl:text> in unsigned long </xsl:text>
+ <xsl:text>PRUint32 </xsl:text>
<xsl:value-of select="@name"/>
- <xsl:text>Size,&#x0A;</xsl:text>
+ <xsl:text>Size, </xsl:text>
<!-- array pointer -->
- <xsl:text> [array, size_is(</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>Size)] in </xsl:text>
<xsl:apply-templates select="@type" mode="forwarder"/>
- <xsl:text> </xsl:text>
+ <xsl:text> *</xsl:text>
<xsl:value-of select="@name"/>
- <xsl:text>&#x0A; );&#x0A;</xsl:text>
+ <xsl:text>);&#x0A;</xsl:text>
</xsl:if>
</xsl:when>
<!-- normal attribute -->
diff --git a/src/VBox/Main/glue/AutoLock.cpp b/src/VBox/Main/glue/AutoLock.cpp
index 1951ac189..bf1d4c9a9 100644
--- a/src/VBox/Main/glue/AutoLock.cpp
+++ b/src/VBox/Main/glue/AutoLock.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -65,15 +65,15 @@ void InitAutoLockSystem()
const char *pcszDescription;
} aClasses[] =
{
- { LOCKCLASS_VIRTUALBOXOBJECT, "1-VIRTUALBOXOBJECT" },
+ { LOCKCLASS_VIRTUALBOXOBJECT, "2-VIRTUALBOXOBJECT" },
{ LOCKCLASS_HOSTOBJECT, "3-HOSTOBJECT" },
{ LOCKCLASS_LISTOFMACHINES, "4-LISTOFMACHINES" },
{ LOCKCLASS_MACHINEOBJECT, "5-MACHINEOBJECT" },
{ LOCKCLASS_SNAPSHOTOBJECT, "6-SNAPSHOTOBJECT" },
- { LOCKCLASS_LISTOFMEDIA, "7-LISTOFMEDIA" },
- { LOCKCLASS_LISTOFOTHEROBJECTS, "8-LISTOFOTHEROBJECTS" },
- { LOCKCLASS_OTHEROBJECT, "9-OTHEROBJECT" },
- { LOCKCLASS_USBLIST, "10-USBLIST" },
+ { LOCKCLASS_MEDIUMQUERY, "7-MEDIUMQUERY" },
+ { LOCKCLASS_LISTOFMEDIA, "8-LISTOFMEDIA" },
+ { LOCKCLASS_LISTOFOTHEROBJECTS, "9-LISTOFOTHEROBJECTS" },
+ { LOCKCLASS_OTHEROBJECT, "10-OTHEROBJECT" },
{ LOCKCLASS_PROGRESSLIST, "11-PROGRESSLIST" },
{ LOCKCLASS_OBJECTSTATE, "12-OBJECTSTATE" }
};
@@ -301,7 +301,6 @@ WriteLockHandle::~WriteLockHandle()
////////////////////////////////////////////////////////////////////////////////
typedef std::vector<LockHandle*> HandlesVector;
-typedef std::vector<uint32_t> CountsVector;
struct AutoLockBase::Data
{
@@ -313,8 +312,7 @@ struct AutoLockBase::Data
#endif
)
: fIsLocked(false),
- aHandles(cHandles), // size of array
- acUnlockedInLeave(cHandles)
+ aHandles(cHandles) // size of array
#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
, pcszFile(pcszFile_),
uLine(uLine_),
@@ -322,10 +320,7 @@ struct AutoLockBase::Data
#endif
{
for (uint32_t i = 0; i < cHandles; ++i)
- {
- acUnlockedInLeave[i] = 0;
aHandles[i] = NULL;
- }
}
bool fIsLocked; // if true, then all items in aHandles are locked by this AutoLock and
@@ -333,7 +328,6 @@ struct AutoLockBase::Data
HandlesVector aHandles; // array (vector) of LockHandle instances; in the case of AutoWriteLock
// and AutoReadLock, there will only be one item on the list; with the
// AutoMulti* derivatives, there will be multiple
- CountsVector acUnlockedInLeave; // for each lock handle, how many times the handle was unlocked in leave(); otherwise 0
#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
// information about where the lock occurred (passed down from the AutoLock classes)
@@ -413,38 +407,11 @@ void AutoLockBase::callUnlockOnAllHandles()
/**
* Destructor implementation that can also be called explicitly, if required.
* Restores the exact state before the AutoLock was created; that is, unlocks
- * all contained semaphores and might actually lock them again if leave()
- * was called during the AutoLock's lifetime.
+ * all contained semaphores.
*/
void AutoLockBase::cleanup()
{
- bool fAnyUnlockedInLeave = false;
-
- uint32_t i = 0;
- for (HandlesVector::iterator it = m->aHandles.begin();
- it != m->aHandles.end();
- ++it)
- {
- LockHandle *pHandle = *it;
- if (pHandle)
- {
- if (m->acUnlockedInLeave[i])
- {
- // there was a leave() before the destruction: then restore the
- // lock level that might have been set by locks other than our own
- if (m->fIsLocked)
- {
- --m->acUnlockedInLeave[i];
- fAnyUnlockedInLeave = true;
- }
- for (; m->acUnlockedInLeave[i]; --m->acUnlockedInLeave[i])
- callLockImpl(*pHandle);
- }
- }
- ++i;
- }
-
- if (m->fIsLocked && !fAnyUnlockedInLeave)
+ if (m->fIsLocked)
callUnlockOnAllHandles();
}
@@ -454,7 +421,7 @@ void AutoLockBase::cleanup()
*/
void AutoLockBase::acquire()
{
- AssertMsg(!m->fIsLocked, ("m->fIsLocked is true, attempting to lock twice!"));
+ AssertMsgReturnVoid(!m->fIsLocked, ("m->fIsLocked is true, attempting to lock twice!"));
callLockOnAllHandles();
m->fIsLocked = true;
}
@@ -464,7 +431,7 @@ void AutoLockBase::acquire()
*/
void AutoLockBase::release()
{
- AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot release!"));
+ AssertMsgReturnVoid(m->fIsLocked, ("m->fIsLocked is false, cannot release!"));
callUnlockOnAllHandles();
m->fIsLocked = false;
}
@@ -553,85 +520,28 @@ void AutoLockBase::release()
l.unlockWrite();
}
-/**
- * Causes the current thread to completely release the write lock to make
- * the managed semaphore immediately available for locking by other threads.
- *
- * This implies that all nested write locks on the semaphore will be
- * released, even those that were acquired through the calls to #lock()
- * methods of all other AutoWriteLock/AutoReadLock instances managing the
- * <b>same</b> read/write semaphore.
- *
- * After calling this method, the only method you are allowed to call is
- * #enter(). It will acquire the write lock again and restore the same
- * level of nesting as it had before calling #leave().
- *
- * If this instance is destroyed without calling #enter(), the destructor
- * will try to restore the write lock level that existed when #leave() was
- * called minus the number of nested #lock() calls made on this instance
- * itself. This is done to preserve lock levels of other
- * AutoWriteLock/AutoReadLock instances managing the same semaphore (if
- * any). Tiis also means that the destructor may indefinitely block if a
- * write or a read lock is owned by some other thread by that time.
- */
-void AutoWriteLockBase::leave()
-{
- AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot leave()!"));
-
- // unlock in reverse order!
- uint32_t i = m->aHandles.size();
- for (HandlesVector::reverse_iterator it = m->aHandles.rbegin();
- it != m->aHandles.rend();
- ++it)
- {
- --i; // array index is zero based, decrement with every loop since we iterate backwards
- LockHandle *pHandle = *it;
- if (pHandle)
- {
- AssertMsg(m->acUnlockedInLeave[i] == 0, ("m->cUnlockedInLeave[%d] is %d, must be 0! Called leave() twice?", i, m->acUnlockedInLeave[i]));
- m->acUnlockedInLeave[i] = pHandle->writeLockLevel();
- AssertMsg(m->acUnlockedInLeave[i] >= 1, ("m->cUnlockedInLeave[%d] is %d, must be >=1!", i, m->acUnlockedInLeave[i]));
-
- for (uint32_t left = m->acUnlockedInLeave[i];
- left;
- --left)
- callUnlockImpl(*pHandle);
- }
- }
-}
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoWriteLock
+//
+////////////////////////////////////////////////////////////////////////////////
-/**
- * Causes the current thread to restore the write lock level after the
- * #leave() call. This call will indefinitely block if another thread has
- * successfully acquired a write or a read lock on the same semaphore in
- * between.
- */
-void AutoWriteLockBase::enter()
+AutoWriteLock::AutoWriteLock(uint32_t cHandles,
+ LockHandle** pHandles
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(cHandles
+ COMMA_LOCKVAL_SRC_POS_ARGS)
{
- AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot enter()!"));
+ Assert(cHandles);
+ Assert(pHandles);
- uint32_t i = 0;
- for (HandlesVector::iterator it = m->aHandles.begin();
- it != m->aHandles.end();
- ++it)
- {
- LockHandle *pHandle = *it;
- if (pHandle)
- {
- AssertMsg(m->acUnlockedInLeave[i] != 0, ("m->cUnlockedInLeave[%d] is 0! enter() without leave()?", i));
+ for (uint32_t i = 0; i < cHandles; ++i)
+ m->aHandles[i] = pHandles[i];
- for (; m->acUnlockedInLeave[i]; --m->acUnlockedInLeave[i])
- callLockImpl(*pHandle);
- }
- ++i;
- }
+ acquire();
}
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutoWriteLock
-//
-////////////////////////////////////////////////////////////////////////////////
+
/**
* Attaches another handle to this auto lock instance.
@@ -750,5 +660,39 @@ AutoMultiWriteLock3::AutoMultiWriteLock3(LockHandle *pl1,
acquire();
}
+AutoMultiWriteLock4::AutoMultiWriteLock4(Lockable *pl1,
+ Lockable *pl2,
+ Lockable *pl3,
+ Lockable *pl4
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(4
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+{
+ if (pl1)
+ m->aHandles[0] = pl1->lockHandle();
+ if (pl2)
+ m->aHandles[1] = pl2->lockHandle();
+ if (pl3)
+ m->aHandles[2] = pl3->lockHandle();
+ if (pl4)
+ m->aHandles[3] = pl4->lockHandle();
+ acquire();
+}
+
+AutoMultiWriteLock4::AutoMultiWriteLock4(LockHandle *pl1,
+ LockHandle *pl2,
+ LockHandle *pl3,
+ LockHandle *pl4
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(4
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+{
+ m->aHandles[0] = pl1;
+ m->aHandles[1] = pl2;
+ m->aHandles[2] = pl3;
+ m->aHandles[3] = pl4;
+ acquire();
+}
+
} /* namespace util */
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/glue/ErrorInfo.cpp b/src/VBox/Main/glue/ErrorInfo.cpp
index 8d7e31eca..13cdee83b 100644
--- a/src/VBox/Main/glue/ErrorInfo.cpp
+++ b/src/VBox/Main/glue/ErrorInfo.cpp
@@ -254,7 +254,7 @@ void ErrorInfo::init(IVirtualBoxErrorInfo *info)
rc = info->COMGETTER(Next)(next.asOutParam());
if (SUCCEEDED(rc) && !next.isNull())
{
- m_pNext = new ErrorInfo(false /* aDummy */);
+ m_pNext = new ErrorInfo(next);
Assert(m_pNext != NULL);
if (!m_pNext)
rc = E_OUTOFMEMORY;
diff --git a/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp b/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp
deleted file mode 100644
index 6e863edb1..000000000
--- a/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp
+++ /dev/null
@@ -1,388 +0,0 @@
-/* $Id: VirtualBoxErrorInfo.cpp $ */
-
-/** @file
- * MS COM / XPCOM Abstraction Layer:
- * VirtualBoxErrorInfo COM class implementation
- */
-
-/*
- * Copyright (C) 2008-2010 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "VBox/com/VirtualBoxErrorInfo.h"
-
-#include "../include/Logging.h"
-
-#include <list>
-
-namespace com
-{
-
-////////////////////////////////////////////////////////////////////////////////
-// VirtualBoxErrorInfo class
-////////////////////////////////////////////////////////////////////////////////
-
-// public initializer/uninitializer for internal purposes only
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Initializes the error info object with the given error details.
- */
-HRESULT VirtualBoxErrorInfo::init(HRESULT aResultCode,
- const GUID *aIID,
- const char *aComponent,
- const Utf8Str &strText,
- IVirtualBoxErrorInfo *aNext)
-{
- mResultCode = aResultCode;
-
- if (aIID != NULL)
- mIID = *aIID;
-
- mComponent = aComponent;
- mText = strText;
- mNext = aNext;
-
- return S_OK;
-}
-
-// IVirtualBoxErrorInfo properties
-////////////////////////////////////////////////////////////////////////////////
-
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(ResultCode) (LONG *aResultCode)
-{
- if (!aResultCode)
- return E_POINTER;
-
- *aResultCode = mResultCode;
- return S_OK;
-}
-
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(InterfaceID) (BSTR *aIID)
-{
- if (!aIID)
- return E_POINTER;
-
- mIID.toUtf16().cloneTo(aIID);
- return S_OK;
-}
-
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Component) (BSTR *aComponent)
-{
- if (!aComponent)
- return E_POINTER;
-
- mComponent.cloneTo(aComponent);
- return S_OK;
-}
-
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Text) (BSTR *aText)
-{
- if (!aText)
- return E_POINTER;
-
- mText.cloneTo(aText);
- return S_OK;
-}
-
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Next) (IVirtualBoxErrorInfo **aNext)
-{
- if (!aNext)
- return E_POINTER;
-
- /* this will set aNext to NULL if mNext is null */
- return mNext.queryInterfaceTo(aNext);
-}
-
-#if !defined(VBOX_WITH_XPCOM)
-
-/**
- * Initializes itself by fetching error information from the given error info
- * object.
- */
-HRESULT VirtualBoxErrorInfo::init (IErrorInfo *aInfo)
-{
- AssertReturn(aInfo, E_FAIL);
-
- HRESULT rc = S_OK;
-
- /* We don't return a failure if talking to IErrorInfo fails below to
- * protect ourselves from bad IErrorInfo implementations (the
- * corresponding fields will simply remain null in this case). */
-
- mResultCode = S_OK;
- rc = aInfo->GetGUID (mIID.asOutParam());
- AssertComRC (rc);
- rc = aInfo->GetSource (mComponent.asOutParam());
- AssertComRC (rc);
- rc = aInfo->GetDescription (mText.asOutParam());
- AssertComRC (rc);
-
- return S_OK;
-}
-
-// IErrorInfo methods
-////////////////////////////////////////////////////////////////////////////////
-
-STDMETHODIMP VirtualBoxErrorInfo::GetDescription (BSTR *description)
-{
- return COMGETTER(Text) (description);
-}
-
-STDMETHODIMP VirtualBoxErrorInfo::GetGUID (GUID *guid)
-{
- Bstr iid;
- HRESULT rc = COMGETTER(InterfaceID) (iid.asOutParam());
- if (SUCCEEDED(rc))
- *guid = Guid(iid).ref();
- return rc;
-}
-
-STDMETHODIMP VirtualBoxErrorInfo::GetHelpContext (DWORD *pdwHelpContext)
-{
- return E_NOTIMPL;
-}
-
-STDMETHODIMP VirtualBoxErrorInfo::GetHelpFile (BSTR *pbstrHelpFile)
-{
- return E_NOTIMPL;
-}
-
-STDMETHODIMP VirtualBoxErrorInfo::GetSource (BSTR *source)
-{
- return COMGETTER(Component) (source);
-}
-
-#else // !defined(VBOX_WITH_XPCOM)
-
-/**
- * Initializes itself by fetching error information from the given error info
- * object.
- */
-HRESULT VirtualBoxErrorInfo::init(nsIException *aInfo)
-{
- AssertReturn(aInfo, E_FAIL);
-
- HRESULT rc = S_OK;
-
- /* We don't return a failure if talking to nsIException fails below to
- * protect ourselves from bad nsIException implementations (the
- * corresponding fields will simply remain null in this case). */
-
- rc = aInfo->GetResult(&mResultCode);
- AssertComRC(rc);
-
- char *pszMsg;
- rc = aInfo->GetMessage(&pszMsg);
- AssertComRC(rc);
- if (NS_SUCCEEDED(rc))
- {
- mText = Bstr(pszMsg);
- nsMemory::Free(pszMsg);
- }
- else
- mText.setNull();
-
- return S_OK;
-}
-
-// nsIException methods
-////////////////////////////////////////////////////////////////////////////////
-
-/* readonly attribute string message; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetMessage (char **aMessage)
-{
- if (!aMessage)
- return NS_ERROR_INVALID_POINTER;
-
- Utf8Str(mText).cloneTo(aMessage);
- return S_OK;
-}
-
-/* readonly attribute nsresult result; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetResult (nsresult *aResult)
-{
- if (!aResult)
- return NS_ERROR_INVALID_POINTER;
-
- PRInt32 lrc;
- nsresult rc = COMGETTER(ResultCode) (&lrc);
- if (SUCCEEDED(rc))
- *aResult = lrc;
- return rc;
-}
-
-/* readonly attribute string name; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetName (char **aName)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute string filename; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetFilename (char **aFilename)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute PRUint32 lineNumber; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetLineNumber (PRUint32 *aLineNumber)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute PRUint32 columnNumber; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetColumnNumber (PRUint32 *aColumnNumber)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute nsIStackFrame location; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetLocation (nsIStackFrame **aLocation)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* readonly attribute nsIException inner; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetInner (nsIException **aInner)
-{
- ComPtr<IVirtualBoxErrorInfo> info;
- nsresult rv = COMGETTER(Next) (info.asOutParam());
- if (FAILED(rv)) return rv;
- return info.queryInterfaceTo(aInner);
-}
-
-/* readonly attribute nsISupports data; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetData (nsISupports **aData)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/* string toString (); */
-NS_IMETHODIMP VirtualBoxErrorInfo::ToString (char **_retval)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMPL_THREADSAFE_ISUPPORTS2 (VirtualBoxErrorInfo,
- nsIException, IVirtualBoxErrorInfo)
-
-#endif /* !defined(VBOX_WITH_XPCOM) */
-
-////////////////////////////////////////////////////////////////////////////////
-// VirtualBoxErrorInfoGlue class
-////////////////////////////////////////////////////////////////////////////////
-
-// public initializer/uninitializer for internal purposes only
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Initializes the glue object with two given error info chains.
- *
- * @param aHead Chain placed to the beginning.
- * @param aTail Chain placed to the end.
- */
-HRESULT VirtualBoxErrorInfoGlue::init (IVirtualBoxErrorInfo *aHead,
- IVirtualBoxErrorInfo *aTail)
-{
- AssertReturn(aHead != NULL, E_INVALIDARG);
- AssertReturn(aTail != NULL, E_INVALIDARG);
-
- HRESULT rc = S_OK;
-
- typedef std::list <ComPtr<IVirtualBoxErrorInfo> > List;
- List list;
-
- ComPtr<IVirtualBoxErrorInfo> cur = aHead;
-
- do
- {
- ComPtr<IVirtualBoxErrorInfo> next;
- rc = cur->COMGETTER(Next) (next.asOutParam());
- if (FAILED(rc)) return rc;
-
- if (next.isNull())
- break;
-
- list.push_back (next);
- cur = next;
- }
- while (true);
-
- if (list.size() == 0)
- {
- /* simplest case */
- mReal = aHead;
- mNext = aTail;
- return S_OK;
- }
-
- for (List::iterator it = list.end(), prev = it; it != list.begin(); -- it)
- {
- ComObjPtr<VirtualBoxErrorInfoGlue> wrapper;
- rc = wrapper.createObject();
- if (FAILED(rc)) break;
-
- -- prev;
-
- if (it == list.end())
- rc = wrapper->protectedInit (*prev, aTail);
- else
- rc = wrapper->protectedInit (*prev, *it);
-
- *prev = wrapper;
-
- if (FAILED(rc)) break;
- }
-
- mReal = aHead;
- mNext = list.front();
-
- return S_OK;
-}
-
-/**
- * Protected initializer that just sets the data fields as given.
- *
- * @param aReal Real error info object (not NULL) to forward calls to.
- * @param aNext Next error info object (may be NULL).
- */
-HRESULT VirtualBoxErrorInfoGlue::protectedInit (IVirtualBoxErrorInfo *aReal,
- IVirtualBoxErrorInfo *aNext)
-{
- AssertReturn(aReal != NULL, E_INVALIDARG);
-
- mReal = aReal;
- mNext = aNext;
-
- return S_OK;
-}
-
-// IVirtualBoxErrorInfo properties
-////////////////////////////////////////////////////////////////////////////////
-
-STDMETHODIMP VirtualBoxErrorInfoGlue::COMGETTER(Next) (IVirtualBoxErrorInfo **aNext)
-{
- if (!aNext)
- return E_POINTER;
-
- /* this will set aNext to NULL if mNext is null */
- return mNext.queryInterfaceTo(aNext);
-}
-
-#if defined (VBOX_WITH_XPCOM)
-
-NS_IMPL_THREADSAFE_ISUPPORTS2 (VirtualBoxErrorInfoGlue,
- nsIException, IVirtualBoxErrorInfo)
-
-#endif /* defined (VBOX_WITH_XPCOM) */
-
-} /* namespace com */
-
diff --git a/src/VBox/Main/glue/com.cpp b/src/VBox/Main/glue/com.cpp
index 93c3a7de7..f22526628 100644
--- a/src/VBox/Main/glue/com.cpp
+++ b/src/VBox/Main/glue/com.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -40,13 +40,19 @@
#include "VBox/com/Guid.h"
#include "VBox/com/array.h"
+#include <package-generated.h>
+
+#include <iprt/buildconfig.h>
#include <iprt/param.h>
#include <iprt/path.h>
#include <iprt/dir.h>
#include <iprt/env.h>
#include <iprt/string.h>
+#include <iprt/system.h>
+#include <iprt/process.h>
#include <VBox/err.h>
+#include <VBox/version.h>
#ifdef RT_OS_DARWIN
# define VBOX_USER_HOME_SUFFIX "Library/VirtualBox"
@@ -175,7 +181,7 @@ HRESULT GlueCreateInstance(const CLSID &clsid,
#endif // VBOX_WITH_XPCOM
-int GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen)
+int GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen, bool fCreateDir)
{
AssertReturn(aDir, VERR_INVALID_POINTER);
AssertReturn(aDirLen > 0, VERR_BUFFER_OVERFLOW);
@@ -204,13 +210,135 @@ int GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen)
/* ensure the home directory exists */
if (RT_SUCCESS(vrc))
- if (!RTDirExists(aDir))
+ if (!RTDirExists(aDir) && fCreateDir)
vrc = RTDirCreateFullPath(aDir, 0700);
}
return vrc;
}
+static const char *g_pszLogEntity = NULL;
+
+static void vboxHeaderFooter(PRTLOGGER pReleaseLogger, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog)
+{
+ /* some introductory information */
+ static RTTIMESPEC s_TimeSpec;
+ char szTmp[256];
+ if (enmPhase == RTLOGPHASE_BEGIN)
+ RTTimeNow(&s_TimeSpec);
+ RTTimeSpecToString(&s_TimeSpec, szTmp, sizeof(szTmp));
+
+ switch (enmPhase)
+ {
+ case RTLOGPHASE_BEGIN:
+ {
+ bool fOldBuffered = RTLogSetBuffering(pReleaseLogger, true /*fBuffered*/);
+ pfnLog(pReleaseLogger,
+ "VirtualBox %s %s r%u %s (%s %s) release log\n"
+#ifdef VBOX_BLEEDING_EDGE
+ "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n"
+#endif
+ "Log opened %s\n",
+ g_pszLogEntity, VBOX_VERSION_STRING, RTBldCfgRevision(),
+ RTBldCfgTargetDotArch(), __DATE__, __TIME__, szTmp);
+
+ int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
+ if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
+ pfnLog(pReleaseLogger, "OS Product: %s\n", szTmp);
+ vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
+ if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
+ pfnLog(pReleaseLogger, "OS Release: %s\n", szTmp);
+ vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
+ if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
+ pfnLog(pReleaseLogger, "OS Version: %s\n", szTmp);
+ vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp));
+ if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
+ pfnLog(pReleaseLogger, "OS Service Pack: %s\n", szTmp);
+
+ vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szTmp, sizeof(szTmp));
+ if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
+ pfnLog(pReleaseLogger, "DMI Product Name: %s\n", szTmp);
+ vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_VERSION, szTmp, sizeof(szTmp));
+ if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
+ pfnLog(pReleaseLogger, "DMI Product Version: %s\n", szTmp);
+
+ uint64_t cbHostRam = 0, cbHostRamAvail = 0;
+ vrc = RTSystemQueryTotalRam(&cbHostRam);
+ if (RT_SUCCESS(vrc))
+ vrc = RTSystemQueryAvailableRam(&cbHostRamAvail);
+ if (RT_SUCCESS(vrc))
+ pfnLog(pReleaseLogger, "Host RAM: %lluMB total, %lluMB available\n",
+ cbHostRam / _1M, cbHostRamAvail / _1M);
+
+ /* the package type is interesting for Linux distributions */
+ char szExecName[RTPATH_MAX];
+ char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
+ pfnLog(pReleaseLogger,
+ "Executable: %s\n"
+ "Process ID: %u\n"
+ "Package type: %s"
+#ifdef VBOX_OSE
+ " (OSE)"
+#endif
+ "\n",
+ pszExecName ? pszExecName : "unknown",
+ RTProcSelf(),
+ VBOX_PACKAGE_STRING);
+ RTLogSetBuffering(pReleaseLogger, fOldBuffered);
+ break;
+ }
+ case RTLOGPHASE_PREROTATE:
+ pfnLog(pReleaseLogger, "Log rotated - Log started %s\n", szTmp);
+ break;
+
+ case RTLOGPHASE_POSTROTATE:
+ pfnLog(pReleaseLogger, "Log continuation - Log started %s\n", szTmp);
+ break;
+
+ case RTLOGPHASE_END:
+ pfnLog(pReleaseLogger, "End of log file - Log started %s\n", szTmp);
+ break;
+
+ default:
+ /* nothing */;
+ }
+}
+
+int VBoxLogRelCreate(const char *pcszEntity, const char *pcszLogFile,
+ uint32_t fFlags, const char *pcszGroupSettings,
+ const char *pcszEnvVarBase, uint32_t fDestFlags,
+ uint32_t cMaxEntriesPerGroup, uint32_t cHistory,
+ uint32_t uHistoryFileTime, uint64_t uHistoryFileSize,
+ char *pszError, size_t cbError)
+{
+ Assert(cbError >= RTPATH_MAX + 128);
+
+ /* create release logger */
+ PRTLOGGER pReleaseLogger;
+ static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
+ fFlags |= RTLOGFLAGS_USECRLF;
+#endif
+ g_pszLogEntity = pcszEntity;
+ int vrc = RTLogCreateEx(&pReleaseLogger, fFlags, "all all.restrict default.unrestricted",
+ pcszEnvVarBase, RT_ELEMENTS(s_apszGroups), s_apszGroups, fDestFlags,
+ vboxHeaderFooter, cHistory, uHistoryFileSize, uHistoryFileTime,
+ pszError, cbError, pcszLogFile);
+ if (RT_SUCCESS(vrc))
+ {
+ /* make sure that we don't flood logfiles */
+ RTLogSetGroupLimit(pReleaseLogger, cMaxEntriesPerGroup);
+
+ /* explicitly flush the log, to have some info when buffering */
+ RTLogFlush(pReleaseLogger);
+
+ /* register this logger as the release logger */
+ RTLogRelSetDefaultInstance(pReleaseLogger);
+ }
+ return vrc;
+}
+
+
/* static */
const Guid Guid::Empty; /* default ctor is OK */
diff --git a/src/VBox/Main/glue/constants-python.xsl b/src/VBox/Main/glue/constants-python.xsl
index e5c672f02..df18f43b2 100644
--- a/src/VBox/Main/glue/constants-python.xsl
+++ b/src/VBox/Main/glue/constants-python.xsl
@@ -8,15 +8,15 @@
XSLT stylesheet that generates VirtualBox_constants.py from
VirtualBox.xidl.
- Copyright (C) 2009 Oracle Corporation
+ Copyright (C) 2009 Oracle Corporation
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:output
diff --git a/src/VBox/Main/glue/errorprint.cpp b/src/VBox/Main/glue/errorprint.cpp
index 3e8c9caf0..45979d629 100644
--- a/src/VBox/Main/glue/errorprint.cpp
+++ b/src/VBox/Main/glue/errorprint.cpp
@@ -22,6 +22,8 @@
#include <VBox/com/errorprint.h>
#include <VBox/log.h>
+#include <ProgressImpl.h>
+
#include <iprt/stream.h>
#include <iprt/message.h>
#include <iprt/path.h>
@@ -29,17 +31,49 @@
namespace com
{
-void GluePrintErrorInfo(com::ErrorInfo &info)
+void GluePrintErrorInfo(const com::ErrorInfo &info)
{
- Utf8Str str = Utf8StrFmt("%ls\n"
- "Details: code %Rhrc (0x%RX32), component %ls, interface %ls, callee %ls\n"
- ,
- info.getText().raw(),
- info.getResultCode(),
- info.getResultCode(),
- info.getComponent().raw(),
- info.getInterfaceName().raw(),
- info.getCalleeName().raw());
+ bool haveResultCode = false;
+#if defined (RT_OS_WIN)
+ haveResultCode = info.isFullAvailable();
+ bool haveComponent = true;
+ bool haveInterfaceID = true;
+#else /* defined (RT_OS_WIN) */
+ haveResultCode = true;
+ bool haveComponent = info.isFullAvailable();
+ bool haveInterfaceID = info.isFullAvailable();
+#endif
+
+ Utf8Str str;
+ RTCList<Utf8Str> comp;
+
+ Bstr bstrDetailsText = info.getText();
+ if (!bstrDetailsText.isEmpty())
+ str = Utf8StrFmt("%ls\n",
+ bstrDetailsText.raw());
+ if (haveResultCode)
+ comp.append(Utf8StrFmt("code %Rhrc (0x%RX32)",
+ info.getResultCode(),
+ info.getResultCode()));
+ if (haveComponent)
+ comp.append(Utf8StrFmt("component %ls",
+ info.getComponent().raw()));
+ if (haveInterfaceID)
+ comp.append(Utf8StrFmt("interface %ls",
+ info.getInterfaceName().raw()));
+ if (!info.getCalleeName().isEmpty())
+ comp.append(Utf8StrFmt("callee %ls",
+ info.getCalleeName().raw()));
+
+ if (comp.size() > 0)
+ {
+ str += "Details: ";
+ for (size_t i = 0; i < comp.size() - 1; ++i)
+ str += comp.at(i) + ", ";
+ str += comp.last();
+ str += "\n";
+ }
+
// print and log
RTMsgError("%s", str.c_str());
Log(("ERROR: %s", str.c_str()));
@@ -51,11 +85,11 @@ void GluePrintErrorContext(const char *pcszContext, const char *pcszSourceFile,
// which we don't want to see printed:
Utf8Str strFilename(RTPathFilename(pcszSourceFile));
Utf8Str str = Utf8StrFmt("Context: \"%s\" at line %d of file %s\n",
- pcszContext,
- ulLine,
- strFilename.c_str());
+ pcszContext,
+ ulLine,
+ strFilename.c_str());
// print and log
- RTStrmPrintf(g_pStdErr, "%s", str.c_str());
+ RTMsgError("%s", str.c_str());
Log(("%s", str.c_str()));
}
@@ -67,21 +101,72 @@ void GluePrintRCMessage(HRESULT rc)
Log(("ERROR: %s", str.c_str()));
}
+static void glueHandleComErrorInternal(com::ErrorInfo &info,
+ const char *pcszContext,
+ HRESULT rc,
+ const char *pcszSourceFile,
+ uint32_t ulLine)
+{
+ if (info.isFullAvailable() || info.isBasicAvailable())
+ {
+ const com::ErrorInfo *pInfo = &info;
+ do
+ {
+ GluePrintErrorInfo(*pInfo);
+
+ pInfo = pInfo->getNext();
+ /* If there is more than one error, separate them visually. */
+ if (pInfo)
+ {
+ /* If there are several errors then at least basic error
+ * information must be available, otherwise something went
+ * horribly wrong. */
+ Assert(pInfo->isFullAvailable() || pInfo->isBasicAvailable());
+
+ RTMsgError("--------\n");
+ }
+ }
+ while (pInfo);
+ }
+ else
+ GluePrintRCMessage(rc);
+
+ GluePrintErrorContext(pcszContext, pcszSourceFile, ulLine);
+}
+
void GlueHandleComError(ComPtr<IUnknown> iface,
const char *pcszContext,
HRESULT rc,
const char *pcszSourceFile,
uint32_t ulLine)
{
- // if we have full error info, print something nice, and start with the actual error message
+ /* If we have full error info, print something nice, and start with the
+ * actual error message. */
com::ErrorInfo info(iface, COM_IIDOF(IUnknown));
- if (info.isFullAvailable() || info.isBasicAvailable())
- GluePrintErrorInfo(info);
- else
- GluePrintRCMessage(rc);
- GluePrintErrorContext(pcszContext, pcszSourceFile, ulLine);
+
+ glueHandleComErrorInternal(info,
+ pcszContext,
+ rc,
+ pcszSourceFile,
+ ulLine);
+
}
+void GlueHandleComErrorProgress(ComPtr<IProgress> progress,
+ const char *pcszContext,
+ HRESULT rc,
+ const char *pcszSourceFile,
+ uint32_t ulLine)
+{
+ /* Get the error info out of the progress object. */
+ ProgressErrorInfo ei(progress);
+
+ glueHandleComErrorInternal(ei,
+ pcszContext,
+ rc,
+ pcszSourceFile,
+ ulLine);
+}
} /* namespace com */
diff --git a/src/VBox/Main/glue/glue-java.xsl b/src/VBox/Main/glue/glue-java.xsl
index 5b343af74..0bcc4398f 100644
--- a/src/VBox/Main/glue/glue-java.xsl
+++ b/src/VBox/Main/glue/glue-java.xsl
@@ -10,15 +10,15 @@
XSLT stylesheet that generates Java glue code for XPCOM, MSCOM and JAX-WS from
VirtualBox.xidl.
- Copyright (C) 2010-2011 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2010-2011 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:output
diff --git a/src/VBox/Main/glue/string.cpp b/src/VBox/Main/glue/string.cpp
index 09edbeee2..dc15bddcb 100644
--- a/src/VBox/Main/glue/string.cpp
+++ b/src/VBox/Main/glue/string.cpp
@@ -85,6 +85,16 @@ void Utf8Str::cloneTo(char **pstr) const
throw std::bad_alloc();
memcpy(*pstr, c_str(), cb);
}
+
+HRESULT Utf8Str::cloneToEx(char **pstr) const
+{
+ size_t cb = length() + 1;
+ *pstr = (char*)nsMemory::Alloc(cb);
+ if (RT_UNLIKELY(!*pstr))
+ return E_OUTOFMEMORY;
+ memcpy(*pstr, c_str(), cb);
+ return S_OK;
+}
#endif
Utf8Str& Utf8Str::stripTrailingSlash()
@@ -187,4 +197,88 @@ void Utf8Str::copyFrom(CBSTR a_pbstr)
}
}
+/**
+ * A variant of Utf8Str::copyFrom that does not throw any exceptions but returns
+ * E_OUTOFMEMORY instead.
+ *
+ * @param a_pbstr The source string.
+ * @returns S_OK or E_OUTOFMEMORY.
+ */
+HRESULT Utf8Str::copyFromEx(CBSTR a_pbstr)
+{
+ if (a_pbstr && *a_pbstr)
+ {
+ int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr,
+ RTSTR_MAX, // size_t cwcString: translate entire string
+ &m_psz, // char **ppsz: output buffer
+ 0, // size_t cch: if 0, func allocates buffer in *ppsz
+ &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator.
+ if (RT_SUCCESS(vrc))
+ m_cbAllocated = m_cch + 1;
+ else
+ {
+ if ( vrc != VERR_NO_STR_MEMORY
+ && vrc != VERR_NO_MEMORY)
+ {
+ /* ASSUME: input is valid Utf-16. Fake out of memory error. */
+ AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len(a_pbstr) * sizeof(RTUTF16), a_pbstr));
+ }
+
+ m_cch = 0;
+ m_cbAllocated = 0;
+ m_psz = NULL;
+
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ m_cch = 0;
+ m_cbAllocated = 0;
+ m_psz = NULL;
+ }
+ return S_OK;
+}
+
+
+/**
+ * A variant of Utf8Str::copyFromN that does not throw any exceptions but
+ * returns E_OUTOFMEMORY instead.
+ *
+ * @param a_pcszSrc The source string.
+ * @param a_cchSrc The source string.
+ * @returns S_OK or E_OUTOFMEMORY.
+ *
+ * @remarks This calls cleanup() first, so the caller doesn't have to. (Saves
+ * code space.)
+ */
+HRESULT Utf8Str::copyFromExNComRC(const char *a_pcszSrc, size_t a_cchSrc)
+{
+ cleanup();
+ if (a_cchSrc)
+ {
+ m_psz = RTStrAlloc(a_cchSrc + 1);
+ if (RT_LIKELY(m_psz))
+ {
+ m_cch = a_cchSrc;
+ m_cbAllocated = a_cchSrc + 1;
+ memcpy(m_psz, a_pcszSrc, a_cchSrc);
+ m_psz[a_cchSrc] = '\0';
+ }
+ else
+ {
+ m_cch = 0;
+ m_cbAllocated = 0;
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ m_cch = 0;
+ m_cbAllocated = 0;
+ m_psz = NULL;
+ }
+ return S_OK;
+}
+
} /* namespace com */
diff --git a/src/VBox/Main/glue/tests/TestVBox.java b/src/VBox/Main/glue/tests/TestVBox.java
index 8da41fdbc..0a7038313 100644
--- a/src/VBox/Main/glue/tests/TestVBox.java
+++ b/src/VBox/Main/glue/tests/TestVBox.java
@@ -14,7 +14,7 @@
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
-import org.virtualbox_4_1.*;
+import org.virtualbox_4_2.*;
import java.util.List;
import java.util.Arrays;
import java.math.BigInteger;
diff --git a/src/VBox/Main/glue/vboxapi.py b/src/VBox/Main/glue/vboxapi.py
index 27fb41a2e..66bc71bc9 100644..100755
--- a/src/VBox/Main/glue/vboxapi.py
+++ b/src/VBox/Main/glue/vboxapi.py
@@ -1,14 +1,15 @@
-#
-# Copyright (C) 2009 Oracle Corporation
-#
-# This file is part of VirtualBox Open Source Edition (OSE), as
-# available from http://www.virtualbox.org. This file is free software;
-# you can redistribute it and/or modify it under the terms of the GNU
-# General Public License (GPL) as published by the Free Software
-# Foundation, in version 2 as it comes in the "COPYING" file of the
-# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-#
+"""
+Copyright (C) 2009-2012 Oracle Corporation
+
+This file is part of VirtualBox Open Source Edition (OSE), as
+available from http://www.virtualbox.org. This file is free software;
+you can redistribute it and/or modify it under the terms of the GNU
+General Public License (GPL) as published by the Free Software
+Foundation, in version 2 as it comes in the "COPYING" file of the
+VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+"""
+
import sys,os
import traceback
diff --git a/src/VBox/Main/idl/VirtualBox.xidl b/src/VBox/Main/idl/VirtualBox.xidl
index e04180182..ee09bde2b 100644
--- a/src/VBox/Main/idl/VirtualBox.xidl
+++ b/src/VBox/Main/idl/VirtualBox.xidl
@@ -2,7 +2,7 @@
<!--
- Copyright (C) 2006-2011 Oracle Corporation
+ Copyright (C) 2006-2012 Oracle Corporation
This file is part of VirtualBox Open Source Edition (OSE), as
available from http://www.virtualbox.org. This file is free software;
@@ -106,6 +106,13 @@
process which issues the object instantiation call. <tt>Session</tt> objects
represent virtual machine sessions which are used to configure virtual
machines and control their execution.
+
+ The naming of methods and attributes is very clearly defined: they all start
+ with a lowercase letter (except if they start with an acronym), and are using
+ CamelCase style otherwise. This naming only applies to the IDL description,
+ and is modified by the various language bindings (some convert the first
+ character to upper case, some not). See the SDK reference for more details
+ about how to call a method or attribute from a specific programming language.
</desc>
<if target="midl">
@@ -487,9 +494,16 @@
NetworkAdapter changes: bandwidth group.
-->
</const>
+ <const name="v1_13" value="15">
+ <desc>Settings version "1.13", written by VirtualBox 4.2.x.</desc>
+ <!--
+ Machine changes: tracing config, groups, autostart;
+ NetworkAdapter changes: unit for bandwidth group limits.
+ -->
+ </const>
<const name="Future" value="99999">
- <desc>Settings version greater than "1.12", written by a future VirtualBox version.</desc>
+ <desc>Settings version greater than "1.13", written by a future VirtualBox version.</desc>
</const>
</enum>
@@ -835,7 +849,7 @@
<desc>
In <link to="IMachine::sessionState"/>, this means that the machine
is currently locked for a session, whose process identifier can
- then be found in the <link to="IMachine::sessionPid" /> attribute.
+ then be found in the <link to="IMachine::sessionPID" /> attribute.
In <link to="ISession::state"/>, this means that a machine is
currently locked for this session, and the mutable machine object
@@ -953,7 +967,7 @@
<enum
name="LockType"
- uuid="138b53f8-db4b-47c5-b32b-4ef52f769413"
+ uuid="168a6a8e-12fd-4878-a1f9-38a750a56089"
>
<desc>
Used with <link to="IMachine::lockMachine" />.
@@ -964,6 +978,10 @@
<const name="Shared" value="1">
<desc>Request only a shared read lock for remote-controlling the machine.</desc>
</const>
+ <const name="VM" value="3">
+ <desc>Lock the machine for writing, and create objects necessary for
+ running a VM in this process.</desc>
+ </const>
</enum>
<enum
@@ -1060,6 +1078,20 @@
</enum>
<enum
+ name="DragAndDropMode"
+ uuid="b618ea0e-b6fb-4f8d-97f7-5e237e49b547"
+ >
+ <desc>
+ Drag'n'Drop interchange mode.
+ </desc>
+
+ <const name="Disabled" value="0"/>
+ <const name="HostToGuest" value="1"/>
+ <const name="GuestToHost" value="2"/>
+ <const name="Bidirectional" value="3"/>
+ </enum>
+
+ <enum
name="Scope"
uuid="7c91096e-499e-4eca-9f9b-9001438d7855"
>
@@ -1127,8 +1159,8 @@
</enum>
<enum
- name="PointingHidType"
- uuid="0d3c17a2-821a-4b2e-ae41-890c6c60aa97"
+ name="PointingHIDType"
+ uuid="e44b2f7b-72ba-44fb-9e53-2186014f0d17"
>
<desc>
Type of pointing device used in a virtual machine.
@@ -1152,8 +1184,8 @@
</enum>
<enum
- name="KeyboardHidType"
- uuid="5a5b0996-3a3e-44bb-9019-56979812cbcc"
+ name="KeyboardHIDType"
+ uuid="383e43d7-5c7c-4ec8-9cb8-eda1bccd6699"
>
<desc>
Type of keyboard device used in a virtual machine.
@@ -1180,7 +1212,7 @@
<interface
name="IVirtualBoxErrorInfo" extends="$errorinfo"
- uuid="e053d3c0-f493-491b-a735-3a9f0b1feed4"
+ uuid="f91e6e91-49e1-4fd2-b21e-269003350d06"
supportsErrorInfo="no"
wsmap="managed"
>
@@ -1284,15 +1316,15 @@
wsmap="managed"
>
<desc>
- The IDHCPServer interface represents the vbox dhcp server configuration.
+ The IDHCPServer interface represents the vbox DHCP server configuration.
- To enumerate all the dhcp servers on the host, use the
+ To enumerate all the DHCP servers on the host, use the
<link to="IVirtualBox::DHCPServers"/> attribute.
</desc>
<attribute name="enabled" type="boolean">
<desc>
- specifies if the dhcp server is enabled
+ specifies if the DHCP server is enabled
</desc>
</attribute>
@@ -1391,7 +1423,7 @@
<interface
name="IVirtualBox" extends="$unknown"
- uuid="c28be65f-1a8f-43b4-81f1-eb60cb516e66"
+ uuid="3b2f08eb-b810-4715-bee0-bb06b9880ad2"
wsmap="managed"
>
<desc>
@@ -1414,6 +1446,19 @@
A string representing the version number of the product. The
format is 3 integer numbers divided by dots (e.g. 1.0.1). The
last number represents the build number and will frequently change.
+
+ This may be followed by a _ALPHA[0-9]*, _BETA[0-9]* or _RC[0-9]* tag
+ in prerelease builds. Non-Oracle builds may (/shall) also have a
+ publisher tag, at the end. The publisher tag starts with an underscore
+ just like the prerelease build type tag.
+ </desc>
+ </attribute>
+
+ <attribute name="versionNormalized" type="wstring" readonly="yes">
+ <desc>
+ A string representing the version number of the product,
+ without the publisher information (but still with other tags).
+ See <link to="#version" />.
</desc>
</attribute>
@@ -1483,6 +1528,16 @@
</desc>
</attribute>
+ <attribute name="machineGroups" type="wstring" readonly="yes" safearray="yes">
+ <desc>
+ Array of all machine group names which are used by the machines which
+ are accessible. Each group is only listed once, however they are listed
+ in no particular order and there is no guarantee that there are no gaps
+ in the group hierarchy (i.e. <tt>"/"</tt>, <tt>"/group/subgroup"</tt>
+ is a valid result).
+ </desc>
+ </attribute>
+
<attribute name="hardDisks" type="IMedium" readonly="yes" safearray="yes">
<desc>
Array of medium objects known to this VirtualBox installation.
@@ -1570,9 +1625,10 @@
This API serves two purposes:
<ul>
- <li>It gets called by <link to="#createMachine" /> if NULL is specified
- for the @a settingsFile argument there, which means that API should use
- a recommended default file name.</li>
+ <li>It gets called by <link to="#createMachine" /> if @c null or
+ empty string (which is recommended) is specified for the
+ @a settingsFile argument there, which means that API should use
+ a recommended default file name.</li>
<li>It can be called manually by a client software before creating a machine,
e.g. if that client wants to pre-create the machine directory to create
@@ -1585,6 +1641,11 @@
See <link to="IMachine::name"/> and <link to="#createMachine"/> for more
details about the machine name.
+ @a groupName defines which additional subdirectory levels should be
+ included. It must be either a valid group name or @c null or empty
+ string which designates that the machine will not be related to a
+ machine group.
+
If @a baseFolder is a @c null or empty string (which is recommended), the
default machine settings folder
(see <link to="ISystemProperties::defaultMachineFolder" />) will be used as
@@ -1593,11 +1654,18 @@
will be used.
This method does not access the host disks. In particular, it does not check
- for whether a machine of this name already exists.
+ for whether a machine with this name already exists.
</desc>
<param name="name" type="wstring" dir="in">
<desc>Suggested machine name.</desc>
</param>
+ <param name="group" type="wstring" dir="in">
+ <desc>Machine group name for the new machine or machine group. It is
+ used to determine the right subdirectory.</desc>
+ </param>
+ <param name="createFlags" type="wstring" dir="in">
+ <desc>Machine creation flags, see <link to="#createMachine" /> (optional).</desc>
+ </param>
<param name="baseFolder" type="wstring" dir="in">
<desc>Base machine folder (optional).</desc>
</param>
@@ -1615,15 +1683,16 @@
with VirtualBox 4.0, a ".vbox" extension is recommended, but not enforced,
and machine files can be created at arbitrary locations.
- However, it is is recommended that machines be created in the default
+ However, it is recommended that machines are created in the default
machine folder (e.g. "/home/user/VirtualBox VMs/name/name.vbox"; see
<link to="ISystemProperties::defaultMachineFolder" />). If you specify
- NULL for the @a settingsFile argument, <link to="#composeMachineFilename" />
- is called automatically to have such a recommended name composed based
- on the machine name given in the @a name argument.
+ @c null or empty string (which is recommended) for the @a settingsFile
+ argument, <link to="#composeMachineFilename" /> is called automatically
+ to have such a recommended name composed based on the machine name
+ given in the @a name argument and the primary group.
If the resulting settings file already exists, this method will fail,
- unless @a forceOverwrite is set.
+ unless the forceOverwrite flag is set.
The new machine is created unregistered, with the initial configuration
set according to the specified guest OS type. A typical sequence of
@@ -1656,12 +1725,6 @@
guest OS types listed in the <link to="IVirtualBox::guestOSTypes"/>
array.
- Optionally, you may specify an UUID of to assign to the created machine.
- However, this is not recommended and you should normally pass an empty
- (@c null) UUID to this method so that a new UUID will be automatically
- generated for every created machine. You can use UUID
- 00000000-0000-0000-0000-000000000000 as @c null value.
-
<note>
There is no way to change the name of the settings file or
subfolder of the created machine directly.
@@ -1681,20 +1744,30 @@
<param name="settingsFile" type="wstring" dir="in">
<desc>Fully qualified path where the settings file should be created,
- or NULL for a default folder and file based on the @a name argument
+ empty string or @c null for a default folder and file based on the
+ @a name argument and the primary group.
(see <link to="#composeMachineFilename" />).</desc>
</param>
<param name="name" type="wstring" dir="in">
<desc>Machine name.</desc>
</param>
+ <param name="groups" type="wstring" safearray="yes" dir="in">
+ <desc>Array of group names. @c null or an empty array have the same
+ meaning as an array with just the empty string or <tt>"/"</tt>, i.e.
+ create a machine without group association.</desc>
+ </param>
<param name="osTypeId" type="wstring" dir="in">
<desc>Guest OS Type ID.</desc>
</param>
- <param name="id" type="uuid" mod="string" dir="in">
- <desc>Machine UUID (optional).</desc>
- </param>
- <param name="forceOverwrite" type="boolean" dir="in">
- <desc>If true, an existing machine settings file will be overwritten.</desc>
+ <param name="flags" type="wstring" dir="in">
+ <desc>
+ Additional property parameters, passed as a comma-separated list of
+ "name=value" type entries. The following ones are recognized:
+ <tt>forceOverwrite=1</tt> to overwrite an existing machine settings
+ file, <tt>UUID=&lt;uuid&gt;</tt> to specify a machine UUID and
+ <tt>directoryIncludesUUID=1</tt> to switch to a special VM directory
+ naming scheme which should not be used unless necessary.
+ </desc>
</param>
<param name="machine" type="IMachine" dir="return">
<desc>Created machine object.</desc>
@@ -1775,6 +1848,32 @@
</param>
</method>
+ <method name="getMachinesByGroups">
+ <desc>
+ Gets all machine references which are in one of the specified groups.
+ </desc>
+ <param name="groups" type="wstring" dir="in" safearray="yes">
+ <desc>What groups to match. The usual group list rules apply, i.e.
+ passing an empty list will match VMs in the toplevel group, likewise
+ the empty string.</desc>
+ </param>
+ <param name="machines" type="IMachine" dir="return" safearray="yes">
+ <desc>All machines which matched.</desc>
+ </param>
+ </method>
+
+ <method name="getMachineStates">
+ <desc>
+ Gets the state of several machines in a single operation.
+ </desc>
+ <param name="machines" type="IMachine" dir="in" safearray="yes">
+ <desc>Array with the machine references.</desc>
+ </param>
+ <param name="states" type="MachineState" dir="return" safearray="yes">
+ <desc>Machine states, corresponding to the machines.</desc>
+ </param>
+ </method>
+
<method name="createAppliance">
<desc>
Creates a new appliance object, which represents an appliance in the Open Virtual Machine
@@ -1805,7 +1904,7 @@
created by one of the above methods.
After the storage unit is successfully created, it will be
- accessible through the <link to="#findMedium"/> method and can
+ accessible through the <link to="#openMedium"/> method and can
be found in the <link to="#hardDisks"/> array.
The list of all storage formats supported by this VirtualBox
@@ -1843,7 +1942,7 @@
<method name="openMedium">
<desc>
- Opens a medium from an existing storage location.
+ Finds existing media or opens a medium from an existing storage location.
Once a medium has been opened, it can be passed to other VirtualBox
methods, in particular to <link to="IMachine::attachDevice" />.
@@ -1865,14 +1964,15 @@
<link to="#floppyImages"/> array attribute.</li>
</ul>
- After having been opened, the medium can be found by the <link to="#findMedium"/>
- method and can be attached to virtual machines. See <link to="IMedium" /> for more details.
+ After having been opened, the medium can be re-found by this method
+ and can be attached to virtual machines. See <link to="IMedium" /> for
+ more details.
The UUID of the newly opened medium will either be retrieved from the
storage location, if the format supports it (e.g. for hard disk images),
or a new UUID will be randomly generated (e.g. for ISO and RAW files).
If for some reason you need to change the medium's UUID, use
- <link to="IMedium::setIDs" />.
+ <link to="IMedium::setIds" />.
If a differencing hard disk medium is to be opened by this method, the
operation will succeed only if its parent medium and all ancestors,
@@ -1936,37 +2036,6 @@
</param>
</method>
- <method name="findMedium">
- <desc>
- Returns a medium of the given type that uses the given fully qualified
- location or UUID to store medium data.
-
- The given medium must be known to this VirtualBox installation, i.e.
- it must be previously created by <link to="#createHardDisk"/> or opened
- by <link to="#openMedium"/>.
-
- The search is done by comparing the value of the @a location argument to
- the <link to="IMedium::location"/> and <link to="IMedium::id" />
- attributes of each known medium.
-
- On case sensitive file systems, a case sensitive comparison is performed,
- otherwise the case of symbols in the file path is ignored.
-
- <result name="VBOX_E_OBJECT_NOT_FOUND">
- No medium object matching @a location found.
- </result>
- </desc>
- <param name="location" type="wstring" dir="in">
- <desc>What to search for. This can either be the UUID or the location string of an open medium.</desc>
- </param>
- <param name="type" type="DeviceType" dir="in">
- <desc>Device type (must be HardDisk, DVD or Floppy)</desc>
- </param>
- <param name="medium" type="IMedium" dir="return">
- <desc>Medium object, if found.</desc>
- </param>
- </method>
-
<method name="getGuestOSType">
<desc>
Returns an object describing the specified guest OS type.
@@ -2109,9 +2178,26 @@
</param>
</method>
+ <method name="setSettingsSecret">
+ <desc>
+ Unlocks the secret data by passing the unlock password to the
+ server. The server will cache the password for that machine.
+
+ <result name="VBOX_E_INVALID_VM_STATE">
+ Virtual machine is not mutable.
+ </result>
+
+ </desc>
+ <param name="password" type="wstring" dir="in">
+ <desc>
+ The cipher key.
+ </desc>
+ </param>
+ </method>
+
<!--method name="createDHCPServerForInterface">
<desc>
- Creates a dhcp server settings to be used for the given interface
+ Creates a DHCP server settings to be used for the given interface
<result name="E_INVALIDARG">
Host network interface @a name already exists.
</result>
@@ -2120,13 +2206,13 @@
<desc>Network Interface</desc>
</param>
<param name="server" type="IDHCPServer" dir="out">
- <desc>Dhcp server settings</desc>
+ <desc>DHCP server settings</desc>
</param>
</method-->
<method name="createDHCPServer">
<desc>
- Creates a dhcp server settings to be used for the given internal network name
+ Creates a DHCP server settings to be used for the given internal network name
<result name="E_INVALIDARG">
Host network interface @a name already exists.
</result>
@@ -2135,13 +2221,13 @@
<desc>server name</desc>
</param>
<param name="server" type="IDHCPServer" dir="return">
- <desc>Dhcp server settings</desc>
+ <desc>DHCP server settings</desc>
</param>
</method>
<method name="findDHCPServerByNetworkName">
<desc>
- Searches a dhcp server settings to be used for the given internal network name
+ Searches a DHCP server settings to be used for the given internal network name
<result name="E_INVALIDARG">
Host network interface @a name already exists.
</result>
@@ -2151,13 +2237,13 @@
<desc>server name</desc>
</param>
<param name="server" type="IDHCPServer" dir="return">
- <desc>Dhcp server settings</desc>
+ <desc>DHCP server settings</desc>
</param>
</method>
<!--method name="findDHCPServerForInterface">
<desc>
- Searches a dhcp server settings to be used for the given interface
+ Searches a DHCP server settings to be used for the given interface
<result name="E_INVALIDARG">
Host network interface @a name already exists.
</result>
@@ -2166,19 +2252,19 @@
<desc>Network Interface</desc>
</param>
<param name="server" type="IDHCPServer" dir="out">
- <desc>Dhcp server settings</desc>
+ <desc>DHCP server settings</desc>
</param>
</method-->
<method name="removeDHCPServer">
<desc>
- Removes the dhcp server settings
+ Removes the DHCP server settings
<result name="E_INVALIDARG">
Host network interface @a name already exists.
</result>
</desc>
<param name="server" type="IDHCPServer" dir="in">
- <desc>Dhcp server settings to be removed</desc>
+ <desc>DHCP server settings to be removed</desc>
</param>
</method>
@@ -2611,8 +2697,8 @@
</desc>
<param name="format" type="wstring" dir="in">
<desc>
- Output format, as a string. Currently supported formats are "ovf-0.9" and "ovf-1.0";
- future versions of VirtualBox may support additional formats.
+ Output format, as a string. Currently supported formats are "ovf-0.9", "ovf-1.0"
+ and "ovf-2.0"; future versions of VirtualBox may support additional formats.
</desc>
</param>
<param name="manifest" type="boolean" dir="in">
@@ -2957,7 +3043,7 @@
<interface
name="IInternalMachineControl" extends="$unknown"
- uuid="ec824977-e43f-479c-81c9-ac6cae1423a5"
+ uuid="dca36a92-703c-4649-98a4-f40c1ef0c336"
internal="yes"
wsmap="suppress"
>
@@ -3416,9 +3502,9 @@
</param>
</method>
- <method name="reportGuestStatistics">
+ <method name="reportVmStatistics">
<desc>
- Passes collected guest statistics to VBoxSVC.
+ Passes statistics collected by VM (including guest statistics) to VBoxSVC.
</desc>
<param name="validStats" type="unsigned long" dir="in">
<desc>
@@ -3465,6 +3551,12 @@
<param name="memSharedTotal" type="unsigned long" dir="in">
<desc>Total amount of shared memory in the hypervisor.</desc>
</param>
+ <param name="vmNetRx" type="unsigned long" dir="in">
+ <desc>Network receive rate for VM.</desc>
+ </param>
+ <param name="vmNetTx" type="unsigned long" dir="in">
+ <desc>Network transmit rate for VM.</desc>
+ </param>
</method>
</interface>
@@ -3527,7 +3619,6 @@
PXE trace information to the release log.
</desc>
</attribute>
-
</interface>
<enum
@@ -3551,7 +3642,7 @@
</enum>
<interface
- name="IPciAddress" extends="$unknown"
+ name="IPCIAddress" extends="$unknown"
uuid="D88B324F-DB19-4D3B-A1A9-BF5B127199A8"
wsmap="struct"
>
@@ -3594,7 +3685,7 @@
</interface>
<interface
- name="IPciDeviceAttachment" extends="$unknown"
+ name="IPCIDeviceAttachment" extends="$unknown"
uuid="91f33d6f-e621-4f70-a77e-15f0e3c714d5"
wsmap="struct"
>
@@ -3674,10 +3765,34 @@
</enum>
+ <enum
+ name="AutostopType" extends="$unknown"
+ uuid="6bb96740-cf34-470d-aab2-2cd48ea2e10e"
+ >
+
+ <desc>
+ Autostop types, used with <link to="IMachine::autostopType" />.
+ </desc>
+
+ <const name="Disabled" value="1">
+ <desc>Stopping the VM during system shutdown is disabled.</desc>
+ </const>
+ <const name="SaveState" value="2">
+ <desc>The state of the VM will be saved when the system shuts down.</desc>
+ </const>
+ <const name="PowerOff" value="3">
+ <desc>The VM is powered off when the system shuts down.</desc>
+ </const>
+ <const name="AcpiShutdown" value="4">
+ <desc>An ACPI shutdown event is generated.</desc>
+ </const>
+
+ </enum>
+
<interface
name="IMachine" extends="$unknown"
- uuid="5eaa9319-62fc-4b0a-843c-0cb1940f8a91"
+ uuid="22781af3-1c96-4126-9edf-67a020e0e858"
wsmap="managed"
>
<desc>
@@ -3831,6 +3946,17 @@
<desc>UUID of the virtual machine.</desc>
</attribute>
+ <attribute name="groups" type="wstring" safearray="yes">
+ <desc>
+ Array of machine group names of which this machine is a member.
+ <tt>""</tt> and <tt>"/"</tt> are synonyms for the toplevel group. Each
+ group is only listed once, however they are listed in no particular
+ order and there is no guarantee that there are no gaps in the group
+ hierarchy (i.e. <tt>"/group"</tt>,
+ <tt>"/group/subgroup/subsubgroup"</tt> is a valid result).
+ </desc>
+ </attribute>
+
<attribute name="OSTypeId" type="wstring">
<desc>
User-defined identifier of the Guest OS type.
@@ -3854,7 +3980,7 @@
The UUID presented to the guest via memory tables, hardware and guest
properties. For most VMs this is the same as the @a id, but for VMs
which have been cloned or teleported it may be the same as the source
- VM. This latter is because the guest shouldn't notice that it was
+ VM. The latter is because the guest shouldn't notice that it was
cloned or teleported.
</desc>
</attribute>
@@ -3877,7 +4003,7 @@
</desc>
</attribute>
- <attribute name="memorySize" type="unsigned long">
+ <attribute name="memorySize" type="unsigned long">
<desc>System memory size in megabytes.</desc>
</attribute>
@@ -3918,6 +4044,30 @@
</desc>
</attribute>
+ <attribute name="VideoCaptureEnabled" type="boolean" default="false">
+ <desc>
+ This setting determines whether VirtualBox uses video recording to
+ record VM session.</desc>
+ </attribute>
+
+ <attribute name="VideoCaptureFile" type="wstring" default="Test.webm">
+ <desc>
+ This setting determines what filename VirtualBox uses to save
+ the recorded content.</desc>
+ </attribute>
+
+ <attribute name="VideoCaptureWidth" type="unsigned long" default="640">
+ <desc>
+ This setting determines what should be the horizontal resolution of
+ recorded video.</desc>
+ </attribute>
+
+ <attribute name="VideoCaptureHeight" type="unsigned long" default="480">
+ <desc>
+ This setting determines what should be the vertical resolution
+ of recorded video.</desc>
+ </attribute>
+
<attribute name="BIOSSettings" type="IBIOSSettings" readonly="yes">
<desc>Object containing all BIOS settings.</desc>
</attribute>
@@ -3927,19 +4077,19 @@
bootstrap in this VM.</desc>
</attribute>
- <attribute name="pointingHidType" type="PointingHidType">
+ <attribute name="pointingHIDType" type="PointingHIDType">
<desc>Type of pointing HID (such as mouse or tablet) used in this VM.
The default is typically "PS2Mouse" but can vary depending on the
requirements of the guest operating system.</desc>
</attribute>
- <attribute name="keyboardHidType" type="KeyboardHidType">
+ <attribute name="keyboardHIDType" type="KeyboardHIDType">
<desc>Type of keyboard HID used in this VM.
The default is typically "PS2Keyboard" but can vary depending on the
requirements of the guest operating system.</desc>
</attribute>
- <attribute name="hpetEnabled" type="boolean">
+ <attribute name="HPETEnabled" type="boolean">
<desc>This attribute controls if High Precision Event Timer (HPET) is
enabled in this VM. Use this property if you want to provide guests
with additional time source, or if guest requires HPET to function correctly.
@@ -4060,7 +4210,7 @@
</desc>
</attribute>
- <attribute name="sessionPid" type="unsigned long" readonly="yes">
+ <attribute name="sessionPID" type="unsigned long" readonly="yes">
<desc>
Identifier of the session process. This attribute contains the
platform-dependent identifier of the process whose session was
@@ -4172,6 +4322,12 @@
</desc>
</attribute>
+ <attribute name="dragAndDropMode" type="DragAndDropMode">
+ <desc>
+ Which mode is allowed for drag'n'drop.
+ </desc>
+ </attribute>
+
<attribute name="guestPropertyNotificationPatterns" type="wstring">
<desc>
A comma-separated list of simple glob patterns. Changes to guest
@@ -4214,6 +4370,9 @@
The password to check for on the target teleporter. This is just a
very basic measure to prevent simple hacks and operators accidentally
beaming a virtual machine to the wrong place.
+
+ Note that you SET a plain text password while reading back a HASHED
+ password. Setting a hashed password is currently not supported.
</desc>
</attribute>
@@ -4260,32 +4419,87 @@
</desc>
</attribute>
- <attribute name="ioCacheEnabled" type="boolean">
+ <attribute name="IOCacheEnabled" type="boolean">
<desc>
When set to @a true, the builtin I/O cache of the virtual machine
will be enabled.
</desc>
</attribute>
- <attribute name="ioCacheSize" type="unsigned long">
+ <attribute name="IOCacheSize" type="unsigned long">
<desc>
Maximum size of the I/O cache in MB.
</desc>
</attribute>
+ <attribute name="PCIDeviceAssignments" type="IPCIDeviceAttachment" readonly="yes" safearray="yes">
+ <desc>Array of PCI devices assigned to this machine, to get list of all
+ PCI devices attached to the machine use
+ <link to="IConsole::attachedPCIDevices"/> attribute, as this attribute
+ is intended to list only devices additional to what described in
+ virtual hardware config. Usually, this list keeps host's physical
+ devices assigned to the particular machine.
+ </desc>
+ </attribute>
+
<attribute name="bandwidthControl" type="IBandwidthControl" readonly="yes">
<desc>
Bandwidth control manager.
</desc>
</attribute>
- <attribute name="pciDeviceAssignments" type="IPciDeviceAttachment" readonly="yes" safearray="yes">
- <desc>Array of PCI devices assigned to this machine, to get list of all
- PCI devices attached to the machine use
- <link to="IConsole::attachedPciDevices"/> attribute, as this attribute
- is intended to list only devices additional to what described in
- virtual hardware config. Usually, this list keeps host's physical
- devices assigned to the particular machine.
+ <attribute name="tracingEnabled" type="boolean">
+ <desc>
+ Enables the tracing facility in the VMM (including PDM devices +
+ drivers). The VMM will consume about 0.5MB of more memory when
+ enabled and there may be some extra overhead from tracepoints that are
+ always enabled.
+ </desc>
+ </attribute>
+
+ <attribute name="tracingConfig" type="wstring">
+ <desc>
+ Tracepoint configuration to apply at startup when
+ <link to="IMachine::tracingEnabled" /> is true. The string specifies
+ a space separated of tracepoint group names to enable. The special
+ group 'all' enables all tracepoints. Check DBGFR3TracingConfig for
+ more details on available tracepoint groups and such.
+
+ Note that on hosts supporting DTrace (or similar), a lot of the
+ tracepoints may be implemented exclusivly as DTrace probes. So, the
+ effect of the same config may differ between Solaris and Windows for
+ example.
+ </desc>
+ </attribute>
+
+ <attribute name="allowTracingToAccessVM" type="boolean">
+ <desc>
+ Enables tracepoints in PDM devices and drivers to use the VMCPU or VM
+ structures when firing off trace points. This is especially useful
+ with DTrace tracepoints, as it allows you to use the VMCPU or VM
+ pointer to obtain useful information such as guest register state.
+
+ This is disabled by default because devices and drivers normally has no
+ business accessing the VMCPU or VM structures, and are therefore unable
+ to get any pointers to these.
+ </desc>
+ </attribute>
+
+ <attribute name="autostartEnabled" type="boolean">
+ <desc>
+ Enables autostart of the VM during system boot.
+ </desc>
+ </attribute>
+
+ <attribute name="autostartDelay" type="unsigned long">
+ <desc>
+ Number of seconds to wait until the VM should be started during system boot.
+ </desc>
+ </attribute>
+
+ <attribute name="autostopType" type="AutostopType">
+ <desc>
+ Action type to do when the system is shutting down.
</desc>
</attribute>
@@ -4482,9 +4696,9 @@
<li><tt>"sdl"</tt>: VirtualBox SDL front-end</li>
<li><tt>"emergencystop"</tt>: reserved value, used for aborting
the currently running VM or session owner. In this case the
- @a session parameter may be @c NULL (if it is non-null it isn't
+ @a session parameter may be @c null (if it is non-null it isn't
used in any way), and the @a progress return value will be always
- NULL. The operation completes immediately.</li>
+ @c null. The operation completes immediately.</li>
</ul>
</desc>
</param>
@@ -4653,7 +4867,92 @@
specified there.</desc>
</param>
<param name="medium" type="IMedium" dir="in">
- <desc>Medium to mount or NULL for an empty drive.</desc>
+ <desc>Medium to mount or @c null for an empty drive.</desc>
+ </param>
+ </method>
+
+ <method name="attachDeviceWithoutMedium">
+ <desc>
+ Attaches a device and optionally mounts a medium to the given storage
+ controller (<link to="IStorageController" />, identified by @a name),
+ at the indicated port and device.
+
+ This method is intended for managing storage devices in general while a
+ machine is powered off. It can be used to attach and detach fixed
+ and removable media. The following kind of media can be attached
+ to a machine:
+ <ul>
+ <li>
+ For fixed and removable media, you can pass in a medium that was
+ previously opened using <link to="IVirtualBox::openMedium" />.
+ </li>
+
+ <li>Only for storage devices supporting removable media (such as
+ DVDs and floppies) with an empty drive or one of the medium objects listed
+ in the <link to="IHost::DVDDrives" /> and <link to="IHost::floppyDrives"/>
+ arrays to indicate a host drive.
+ For removable devices, you can also use <link to="IMachine::mountMedium"/>
+ to change the media while the machine is running.
+ </li>
+ </ul>
+
+ In a VM's default configuration of virtual machines, the secondary
+ master of the IDE controller is used for a CD/DVD drive.
+ <link to="IMediumAttachment"/> will appear in the machine's list of medium
+ attachments (see <link to="IMachine::mediumAttachments"/>).
+
+ See <link to="IMedium"/> and <link to="IMediumAttachment"/> for more
+ information about attaching media.
+
+ The specified device slot must not have a device attached to it,
+ or this method will fail.
+ <note>
+ You cannot attach a device to a newly created machine until
+ this machine's settings are saved to disk using
+ <link to="#saveSettings"/>.
+ </note>
+ <note>
+ If the medium is being attached indirectly, a new differencing medium
+ will implicitly be created for it and attached instead. If the
+ changes made to the machine settings (including this indirect
+ attachment) are later cancelled using <link to="#discardSettings"/>,
+ this implicitly created differencing medium will implicitly
+ be deleted.
+ </note>
+
+ <result name="E_INVALIDARG">
+ SATA device, SATA port, IDE port or IDE slot out of range, or
+ file or UUID not found.
+ </result>
+ <result name="VBOX_E_INVALID_OBJECT_STATE">
+ Machine must be registered before media can be attached.
+ </result>
+ <result name="VBOX_E_INVALID_VM_STATE">
+ Invalid machine state.
+ </result>
+ <result name="VBOX_E_OBJECT_IN_USE">
+ A medium is already attached to this or another virtual machine.
+ </result>
+ </desc>
+ <param name="name" type="wstring" dir="in">
+ <desc>Name of the storage controller to attach the device to.</desc>
+ </param>
+ <param name="controllerPort" type="long" dir="in">
+ <desc>Port to attach the device to. For an IDE controller, 0 specifies
+ the primary controller and 1 specifies the secondary controller.
+ For a SCSI controller, this must range from 0 to 15; for a SATA controller,
+ from 0 to 29; for an SAS controller, from 0 to 7.</desc>
+ </param>
+ <param name="device" type="long" dir="in">
+ <desc>Device slot in the given port to attach the device to. This is only
+ relevant for IDE controllers, for which 0 specifies the master device and
+ 1 specifies the slave device. For all other controller types, this must
+ be 0.</desc>
+ </param>
+ <param name="type" type="DeviceType" dir="in">
+ <desc>Device type of the attached device. For media opened by
+ <link to="IVirtualBox::openMedium" />, this must match the device type
+ specified there.</desc>
</param>
</method>
@@ -4687,7 +4986,8 @@
No medium attached to given slot/bus.
</result>
<result name="VBOX_E_NOT_SUPPORTED">
- Medium format does not support storage deletion.
+ Medium format does not support storage deletion (only for implicitly
+ created differencing media, should not happen).
</result>
</desc>
@@ -4813,6 +5113,45 @@
</param>
</method>
+ <method name="setAutoDiscardForDevice">
+ <desc>
+ Sets a flag in the device information which indicates that the medium
+ supports discarding unsused blocks (called trimming for SATA or unmap
+ for SCSI devices) .This may or may not be supported by a particular drive,
+ and is silently ignored in the latter case. At the moment only hard disks
+ (which is a misnomer in this context) accept this setting. Changing the
+ setting while the VM is running is forbidden. The device must already
+ exist; see <link to="IMachine::attachDevice"/> for how to attach a new
+ device.
+
+ The @a controllerPort and @a device parameters specify the device slot and
+ have have the same meaning as with <link to="IMachine::attachDevice" />.
+
+ <result name="E_INVALIDARG">
+ SATA device, SATA port, SCSI port out of range.
+ </result>
+ <result name="VBOX_E_INVALID_OBJECT_STATE">
+ Attempt to modify an unregistered virtual machine.
+ </result>
+ <result name="VBOX_E_INVALID_VM_STATE">
+ Invalid machine state.
+ </result>
+
+ </desc>
+ <param name="name" type="wstring" dir="in">
+ <desc>Name of the storage controller.</desc>
+ </param>
+ <param name="controllerPort" type="long" dir="in">
+ <desc>Storage controller port.</desc>
+ </param>
+ <param name="device" type="long" dir="in">
+ <desc>Device slot in the given port.</desc>
+ </param>
+ <param name="discard" type="boolean" dir="in">
+ <desc>New value for the discard device flag.</desc>
+ </param>
+ </method>
+
<method name="setBandwidthGroupForDevice">
<desc>
Sets the bandwidth group of an existing storage device.
@@ -4843,10 +5182,92 @@
<desc>Device slot in the given port.</desc>
</param>
<param name="bandwidthGroup" type="IBandwidthGroup" dir="in">
- <desc>New value for the bandwidth group or NULL for no group.</desc>
+ <desc>New value for the bandwidth group or @c null for no group.</desc>
</param>
</method>
+ <method name="setNoBandwidthGroupForDevice">
+ <desc>
+ Sets no bandwidth group for an existing storage device.
+ The device must already exist; see <link to="IMachine::attachDevice"/>
+ for how to attach a new device.
+ The @a controllerPort and @a device parameters specify the device slot and
+ have have the same meaning as with <link to="IMachine::attachDevice" />.
+ <result name="E_INVALIDARG">
+ SATA device, SATA port, IDE port or IDE slot out of range.
+ </result>
+ <result name="VBOX_E_INVALID_OBJECT_STATE">
+ Attempt to modify an unregistered virtual machine.
+ </result>
+ <result name="VBOX_E_INVALID_VM_STATE">
+ Invalid machine state.
+ </result>
+
+ </desc>
+ <param name="name" type="wstring" dir="in">
+ <desc>Name of the storage controller.</desc>
+ </param>
+ <param name="controllerPort" type="long" dir="in">
+ <desc>Storage controller port.</desc>
+ </param>
+ <param name="device" type="long" dir="in">
+ <desc>Device slot in the given port.</desc>
+ </param>
+ </method>
+
+
+ <method name="unmountMedium">
+ <desc>
+ Unmounts any currently mounted medium (<link to="IMedium" />,
+ identified by the given UUID @a id) to the given storage controller
+ (<link to="IStorageController" />, identified by @a name),
+ at the indicated port and device. The device must already exist;
+
+ This method is intended only for managing removable media, where the
+ device is fixed but media is changeable at runtime (such as DVDs
+ and floppies). It cannot be used for fixed media such as hard disks.
+
+ The @a controllerPort and @a device parameters specify the device slot
+ and have have the same meaning as with
+ <link to="IMachine::attachDevice" />.
+
+ The specified device slot must have a medium mounted, which will be
+ unmounted. If there is no mounted medium it will do nothing.
+ See <link to="IMedium"/> for more detailed information about
+ attaching/unmounting media.
+
+ <result name="E_INVALIDARG">
+ SATA device, SATA port, IDE port or IDE slot out of range.
+ </result>
+ <result name="VBOX_E_INVALID_OBJECT_STATE">
+ Attempt to unmount medium that is not removeable - not dvd or floppy.
+ </result>
+ <result name="VBOX_E_INVALID_VM_STATE">
+ Invalid machine state.
+ </result>
+ <result name="VBOX_E_OBJECT_IN_USE">
+ Medium already attached to this or another virtual machine.
+ </result>
+ <result name="VBOX_E_OBJECT_NOT_FOUND">
+ Medium not attached to specified port, device, controller.
+ </result>
+
+ </desc>
+ <param name="name" type="wstring" dir="in">
+ <desc>Name of the storage controller to unmount the medium from.</desc>
+ </param>
+ <param name="controllerPort" type="long" dir="in">
+ <desc>Port to unmount the medium from.</desc>
+ </param>
+ <param name="device" type="long" dir="in">
+ <desc>Device slot in the given port to unmount the medium from.</desc>
+ </param>
+ <param name="force" type="boolean" dir="in">
+ <desc>Allows to force unmount of a medium which is locked by
+ the device slot in the given port medium is attached to.</desc>
+ </param>
+ </method>
+
<method name="mountMedium">
<desc>
Mounts a medium (<link to="IMedium" />, identified
@@ -4893,7 +5314,7 @@
<desc>Device slot in the given port to attach the medium to.</desc>
</param>
<param name="medium" type="IMedium" dir="in">
- <desc>Medium to mount or NULL for an empty drive.</desc>
+ <desc>Medium to mount or @c null for an empty drive.</desc>
</param>
<param name="force" type="boolean" dir="in">
<desc>Allows to force unmount/mount of a medium which is locked by
@@ -4959,15 +5380,15 @@
<param name="attachment" type="IMediumAttachment" dir="return"/>
</method>
- <method name="attachHostPciDevice">
+ <method name="attachHostPCIDevice">
<desc>
Attaches host PCI device with the given (host) PCI address to the
PCI bus of the virtual machine. Please note, that this operation
is two phase, as real attachment will happen when VM will start,
- and most information will be delivered as IHostPciDevicePlugEvent
+ and most information will be delivered as IHostPCIDevicePlugEvent
on IVirtualBox event source.
- <see><link to="IHostPciDevicePlugEvent"/></see>
+ <see><link to="IHostPCIDevicePlugEvent"/></see>
<result name="VBOX_E_INVALID_VM_STATE">
Virtual machine state is not stopped (PCI hotplug not yet implemented).
@@ -4991,14 +5412,14 @@
</param>
</method>
- <method name="detachHostPciDevice">
+ <method name="detachHostPCIDevice">
<desc>
Detach host PCI device from the virtual machine.
- Also HostPciDevicePlugEvent on IVirtualBox event source
+ Also HostPCIDevicePlugEvent on IVirtualBox event source
will be delivered. As currently we don't support hot device
- unplug, IHostPciDevicePlugEvent event is delivered immediately.
+ unplug, IHostPCIDevicePlugEvent event is delivered immediately.
- <see><link to="IHostPciDevicePlugEvent"/></see>
+ <see><link to="IHostPCIDevicePlugEvent"/></see>
<result name="VBOX_E_INVALID_VM_STATE">
Virtual machine state is not stopped (PCI hotplug not yet implemented).
@@ -5088,11 +5509,15 @@
<method name="removeStorageController">
<desc>
- Removes a storage controller from the machine.
+ Removes a storage controller from the machine with all devices attached to it.
<result name="VBOX_E_OBJECT_NOT_FOUND">
A storage controller with given name doesn't exist.
</result>
+ <result name="VBOX_E_NOT_SUPPORTED">
+ Medium format does not support storage deletion (only for implicitly
+ created differencing media, should not happen).
+ </result>
</desc>
<param name="name" type="wstring" dir="in"/>
</method>
@@ -5897,6 +6322,22 @@
</param>
</method>
+ <method name="deleteGuestProperty" const="yes">
+ <desc>
+ Deletes an entry from the machine's guest property store.
+
+ <result name="VBOX_E_INVALID_VM_STATE">
+ Machine session is not open.
+ </result>
+
+ </desc>
+ <param name="name" type="wstring" dir="in">
+ <desc>
+ The name of the property to delete.
+ </desc>
+ </param>
+ </method>
+
<method name="enumerateGuestProperties" const="yes">
<desc>
Return a list of the guest properties matching a set of patterns along
@@ -5933,7 +6374,7 @@
</param>
</method>
- <method name="querySavedGuestSize" const="yes">
+ <method name="querySavedGuestScreenInfo" const="yes">
<desc>
Returns the guest dimensions from the saved state.
</desc>
@@ -5942,6 +6383,16 @@
Saved guest screen to query info from.
</desc>
</param>
+ <param name="originX" type="unsigned long" dir="out">
+ <desc>
+ The X position of the guest monitor top left corner.
+ </desc>
+ </param>
+ <param name="originY" type="unsigned long" dir="out">
+ <desc>
+ The Y position of the guest monitor top left corner.
+ </desc>
+ </param>
<param name="width" type="unsigned long" dir="out">
<desc>
Guest width at the time of the saved state was taken.
@@ -5952,6 +6403,11 @@
Guest height at the time of the saved state was taken.
</desc>
</param>
+ <param name="enabled" type="boolean" dir="out">
+ <desc>
+ Whether the monitor is enabled in the guest.
+ </desc>
+ </param>
</method>
<method name="querySavedThumbnailSize">
@@ -6327,7 +6783,7 @@
<interface
name="IConsole" extends="$unknown"
- uuid="1968b7d3-e3bf-4ceb-99e0-cb7c913317bb"
+ uuid="db7ab4ca-2a3f-4183-9243-c1208da92392"
wsmap="managed"
>
<desc>
@@ -6454,7 +6910,7 @@
</desc>
</attribute>
- <attribute name="attachedPciDevices" type="IPciDeviceAttachment" readonly="yes" safearray="yes">
+ <attribute name="attachedPCIDevices" type="IPCIDeviceAttachment" readonly="yes" safearray="yes">
<desc>Array of PCI devices attached to this machine.</desc>
</attribute>
@@ -6896,7 +7352,7 @@
<link to="#saveState"/>), Running or
Paused virtual machine. When the machine is PoweredOff, an
offline snapshot is created. When the machine is Running a live
- snapshot is created, and an online snapshot is is created when Paused.
+ snapshot is created, and an online snapshot is created when Paused.
The taken snapshot is always based on the
<link to="IMachine::currentSnapshot">current snapshot</link>
@@ -7220,7 +7676,7 @@
<interface
name="IHostNetworkInterface" extends="$unknown"
- uuid="ce6fae58-7642-4102-b5db-c9005c2320a8"
+ uuid="87a4153d-6889-4dd6-9654-2e9ff0ae8dec"
wsmap="managed"
>
<desc>
@@ -7241,7 +7697,7 @@
<desc>Returns the name of a virtual network the interface gets attached to.</desc>
</attribute>
- <attribute name="dhcpEnabled" type="boolean" readonly="yes">
+ <attribute name="DHCPEnabled" type="boolean" readonly="yes">
<desc>Specifies whether the DHCP is enabled for the interface.</desc>
</attribute>
@@ -7281,7 +7737,7 @@
<desc>specifies the host interface type.</desc>
</attribute>
- <method name="enableStaticIpConfig">
+ <method name="enableStaticIPConfig">
<desc>sets and enables the static IP V4 configuration for the given interface.</desc>
<param name="IPAddress" type="wstring" dir="in">
<desc>
@@ -7295,7 +7751,7 @@
</param>
</method>
- <method name="enableStaticIpConfigV6">
+ <method name="enableStaticIPConfigV6">
<desc>sets and enables the static IP V6 configuration for the given interface.</desc>
<param name="IPV6Address" type="wstring" dir="in">
<desc>
@@ -7309,19 +7765,19 @@
</param>
</method>
- <method name="enableDynamicIpConfig">
+ <method name="enableDynamicIPConfig">
<desc>enables the dynamic IP configuration.</desc>
</method>
- <method name="dhcpRediscover">
- <desc>refreshes the IP configuration for dhcp-enabled interface.</desc>
+ <method name="DHCPRediscover">
+ <desc>refreshes the IP configuration for DHCP-enabled interface.</desc>
</method>
</interface>
<interface
name="IHost" extends="$unknown"
- uuid="dab4a2b8-c735-4f08-94fc-9bec84182e2f"
+ uuid="30678943-32df-4830-b413-931b25ac86a0"
wsmap="managed"
>
<desc>
@@ -7514,7 +7970,7 @@
<desc>Returns the current host time in milliseconds since 1970-01-01 UTC.</desc>
</attribute>
- <attribute name="Acceleration3DAvailable" type="boolean" readonly="yes">
+ <attribute name="acceleration3DAvailable" type="boolean" readonly="yes">
<desc>Returns @c true when the host supports 3D hardware acceleration.</desc>
</attribute>
@@ -7775,7 +8231,7 @@
<interface
name="ISystemProperties"
extends="$unknown"
- uuid="8a0ab9ab-48c1-4d04-954b-4a751413d084"
+ uuid="1d7aca29-97f0-4287-9874-a60ec4f80ea6"
wsmap="managed"
>
<desc>
@@ -8025,6 +8481,19 @@
system.</desc>
</attribute>
+ <attribute name="autostartDatabasePath" type="wstring">
+ <desc>
+ The path to the autostart database. Depending on the host this might
+ be a filesystem path or something else.
+ </desc>
+ </attribute>
+
+ <attribute name="defaultAdditionsISO" type="wstring">
+ <desc>
+ The path to the default Guest Additions ISO image. Can be empty if
+ the location is not known in this installation.
+ </desc>
+ </attribute>
<method name="getMaxNetworkAdapters">
<desc>
@@ -8157,7 +8626,7 @@
<interface
name="IGuestOSType" extends="$unknown"
- uuid="432c1546-1354-4abf-bf08-878a32a373f5"
+ uuid="6d968f9a-858b-4c50-bf17-241f069e94c2"
wsmap="struct"
>
<desc>
@@ -8199,6 +8668,14 @@
<desc>Recommended video RAM size in Megabytes.</desc>
</attribute>
+ <attribute name="recommended2DVideoAcceleration" type="boolean" readonly="yes">
+ <desc>Returns @c true if 2D video acceleration is recommended for this OS type.</desc>
+ </attribute>
+
+ <attribute name="recommended3DAcceleration" type="boolean" readonly="yes">
+ <desc>Returns @c true if 3D acceleration is recommended for this OS type.</desc>
+ </attribute>
+
<attribute name="recommendedHDD" type="long long" readonly="yes">
<desc>Recommended hard disk size in bytes.</desc>
</attribute>
@@ -8207,23 +8684,23 @@
<desc>Returns recommended network adapter for this OS type.</desc>
</attribute>
- <attribute name="recommendedPae" type="boolean" readonly="yes">
+ <attribute name="recommendedPAE" type="boolean" readonly="yes">
<desc>Returns @c true if using PAE is recommended for this OS type.</desc>
</attribute>
- <attribute name="recommendedDvdStorageController" type="StorageControllerType" readonly="yes">
+ <attribute name="recommendedDVDStorageController" type="StorageControllerType" readonly="yes">
<desc>Recommended storage controller type for DVD/CD drives.</desc>
</attribute>
- <attribute name="recommendedDvdStorageBus" type="StorageBus" readonly="yes">
+ <attribute name="recommendedDVDStorageBus" type="StorageBus" readonly="yes">
<desc>Recommended storage bus type for DVD/CD drives.</desc>
</attribute>
- <attribute name="recommendedHdStorageController" type="StorageControllerType" readonly="yes">
+ <attribute name="recommendedHDStorageController" type="StorageControllerType" readonly="yes">
<desc>Recommended storage controller type for HD drives.</desc>
</attribute>
- <attribute name="recommendedHdStorageBus" type="StorageBus" readonly="yes">
+ <attribute name="recommendedHDStorageBus" type="StorageBus" readonly="yes">
<desc>Recommended storage bus type for HD drives.</desc>
</attribute>
@@ -8231,19 +8708,19 @@
<desc>Recommended firmware type.</desc>
</attribute>
- <attribute name="recommendedUsbHid" type="boolean" readonly="yes">
+ <attribute name="recommendedUSBHID" type="boolean" readonly="yes">
<desc>Returns @c true if using USB Human Interface Devices, such as keyboard and mouse recommended.</desc>
</attribute>
- <attribute name="recommendedHpet" type="boolean" readonly="yes">
+ <attribute name="recommendedHPET" type="boolean" readonly="yes">
<desc>Returns @c true if using HPET is recommended for this OS type.</desc>
</attribute>
- <attribute name="recommendedUsbTablet" type="boolean" readonly="yes">
+ <attribute name="recommendedUSBTablet" type="boolean" readonly="yes">
<desc>Returns @c true if using a USB Tablet is recommended.</desc>
</attribute>
- <attribute name="recommendedRtcUseUtc" type="boolean" readonly="yes">
+ <attribute name="recommendedRTCUseUTC" type="boolean" readonly="yes">
<desc>Returns @c true if the RTC of this VM should be set to UTC</desc>
</attribute>
@@ -8255,6 +8732,14 @@
<desc>Recommended audio type.</desc>
</attribute>
+ <attribute name="recommendedFloppy" type="boolean" readonly="yes">
+ <desc>Returns @c true a floppy drive is recommended for this OS type.</desc>
+ </attribute>
+
+ <attribute name="recommendedUSB" type="boolean" readonly="yes">
+ <desc>Returns @c true a USB controller is recommended for this OS type.</desc>
+ </attribute>
+
</interface>
<enum
@@ -8429,77 +8914,26 @@
<desc>No flag set.</desc>
</const>
<const name="WaitForUpdateStartOnly" value="1">
- <desc>Only wait for the update process being started and do not
- wait while peforming the actual update.</desc>
+ <desc>Starts the regular updating process and waits until the
+ actual Guest Additions update inside the guest was started.
+ This can be necessary due to needed interaction with the guest
+ OS during the installation phase.</desc>
</const>
</enum>
<enum
- name="ExecuteProcessFlag"
- uuid="286ceb91-5f66-4c96-9845-4483e90e00ae"
+ name="FileSeekType"
+ uuid="1b73f4f3-3515-4073-a506-76878d9e2541"
>
<desc>
- Guest process execution flags.
+ File seeking types.
</desc>
- <const name="None" value="0">
- <desc>No flag set.</desc>
+ <const name="Set" value="0">
+ <desc>Seek from the start of the file.</desc>
</const>
- <const name="WaitForProcessStartOnly" value="1">
- <desc>Only use the specified timeout value to wait for starting the guest process - the guest
- process itself then uses an infinite timeout.</desc>
- </const>
- <const name="IgnoreOrphanedProcesses" value="2">
- <desc>Do not report an error when executed processes are still alive when VBoxService or the guest OS is shutting down.</desc>
- </const>
- <const name="Hidden" value="4">
- <desc>Do not show the started process according to the guest OS guidelines.</desc>
- </const>
- <const name="NoProfile" value="8">
- <desc>Do not use the user's profile data when exeuting a process.</desc>
- </const>
- <const name="WaitForStdOut" value="16">
- <desc>The guest process waits until all data from stdout is read out.</desc>
- </const>
- <const name="WaitForStdErr" value="32">
- <desc>The guest process waits until all data from stderr is read out.</desc>
- </const>
- </enum>
-
- <enum
- name="ExecuteProcessStatus"
- uuid="153768d9-d971-4098-8b5a-c5cb1ab9ea88"
- >
- <desc>
- Guest process execution status.
- </desc>
- <const name="Undefined" value="0">
- <desc>Process is in an undefined state.</desc>
- </const>
-
- <const name="Started" value="1">
- <desc>Process has been started.</desc>
- </const>
- <const name="TerminatedNormally" value="2">
- <desc>Process terminated normally.</desc>
- </const>
- <const name="TerminatedSignal" value="3">
- <desc>Process terminated via signal.</desc>
- </const>
- <const name="TerminatedAbnormally" value="4">
- <desc>Process terminated abnormally.</desc>
- </const>
- <const name="TimedOutKilled" value="5">
- <desc>Process timed out and was killed.</desc>
- </const>
- <const name="TimedOutAbnormally" value="6">
- <desc>Process timed out and was not killed successfully.</desc>
- </const>
- <const name="Down" value="7">
- <desc>Service/OS is stopping, process was killed.</desc>
- </const>
- <const name="Error" value="8">
- <desc>Something went wrong (error code in flags).</desc>
+ <const name="Current" value="1">
+ <desc>Seek from the current file position.</desc>
</const>
</enum>
@@ -8535,12 +8969,102 @@
</enum>
<enum
+ name="ProcessWaitForFlag"
+ uuid="23b550c7-78e1-437e-98f0-65fd9757bcd2"
+ >
+ <desc>
+ Process waiting flags. Multiple flags can be combined.
+ </desc>
+
+ <const name="None" value="0">
+ <desc>No waiting flags specified. Do not use this.</desc>
+ </const>
+ <const name="Start" value="1">
+ <desc>Wait for the process being started.</desc>
+ </const>
+ <const name="Terminate" value="2">
+ <desc>Wait for the process being terminated.</desc>
+ </const>
+ <const name="StdIn" value="4">
+ <desc>Wait for stdin becoming available.</desc>
+ </const>
+ <const name="StdOut" value="8">
+ <desc>Wait for data becoming available on stdout.</desc>
+ </const>
+ <const name="StdErr" value="16">
+ <desc>Wait for data becoming available on stderr.</desc>
+ </const>
+ </enum>
+
+ <enum
+ name="ProcessWaitResult"
+ uuid="40719cbe-f192-4fe9-a231-6697b3c8e2b4"
+ >
+ <desc>
+ Process waiting results. Depending on the process waiting flags (for
+ more information see <link to="ProcessWaitForFlag"/>) the waiting result
+ can vary based on the processes' current status.
+
+ To wait for a gust process to terminate after it has been
+ created by <link to="IGuestSession::processCreate"/> or <link to="IGuestSession::processCreateEx"/>
+ one would specify ProcessWaitResult_Terminate.
+
+ If a guest process has been started with ProcessCreateFlag_WaitForStdOut
+ a client can wait with ProcessWaitResult_StdOut for new data to arrive on
+ stdout; same applies for ProcessCreateFlag_WaitForStdErr and
+ ProcessWaitResult_StdErr.
+ </desc>
+
+ <const name="None" value="0">
+ <desc>No result was returned. Not being used.</desc>
+ </const>
+ <const name="Start" value="1">
+ <desc>The process has been started.</desc>
+ </const>
+ <const name="Terminate" value="2">
+ <desc>The process has been terminated.</desc>
+ </const>
+ <const name="Status" value="3">
+ <desc>
+ The process has changed its status. The status then can
+ be retrieved via <link to="IProcess::status"/>.
+ </desc>
+ </const>
+ <const name="Error" value="4">
+ <desc>Error while executing the process.</desc>
+ </const>
+ <const name="Timeout" value="5">
+ <desc>
+ The waiting operation timed out. This also will happen
+ when no event has been occured matching the
+ current waiting flags in a <link to="IProcess::waitFor"/> call.
+ </desc>
+ </const>
+ <const name="StdIn" value="6">
+ <desc>
+ The process signalled that stdin became available for writing
+ and that the process awaits input now.</desc>
+ </const>
+ <const name="StdOut" value="7">
+ <desc>Data on stdout became available for reading.</desc>
+ </const>
+ <const name="StdErr" value="8">
+ <desc>Data on stderr became available for reading.</desc>
+ </const>
+ <const name="WaitFlagNotSupported" value="9">
+ <desc>
+ A waiting flag specified in the <link to="IProcess::waitFor"/> call
+ is not supported by the guest.
+ </desc>
+ </const>
+ </enum>
+
+ <enum
name="CopyFileFlag"
uuid="23f79fdf-738a-493d-b80b-42d607c9b916"
>
<desc>
- Host/Guest copy flags. At the moment none of these flags
- are implemented.
+ File copying flags.
</desc>
<const name="None" value="0">
<desc>No flag set.</desc>
@@ -8572,60 +9096,1622 @@
</enum>
<enum
- name="DirectoryOpenFlag"
- uuid="fc8f6203-0072-4f34-bd08-0b35e50bf071"
+ name="DirectoryRemoveRecFlag"
+ uuid="455aabf0-7692-48f6-9061-f21579b65769"
>
<desc>
- Directory open flags.
+ Directory recursive removement flags.
+ </desc>
+
+ <const name="None" value="0">
+ <desc>No flag set.</desc>
+ </const>
+ <const name="ContentAndDir" value="1">
+ <desc>Delete the content of the directory and the directory itself.</desc>
+ </const>
+ <const name="ContentOnly" value="2">
+ <desc>Only delete the content of the directory, omit the directory it self.</desc>
+ </const>
+ </enum>
+
+ <enum
+ name="PathRenameFlag"
+ uuid="f3baa09f-c758-453d-b91c-c7787d76351d"
+ >
+ <desc>
+ Path renaming flags.
+ </desc>
+
+ <const name="None" value="0">
+ <desc>No flag set.</desc>
+ </const>
+ <const name="NoReplace" value="1">
+ <desc>Do not replace anything.</desc>
+ </const>
+ <const name="Replace" value="2">
+ <desc>This will replace attempt any target which isn't a directory.</desc>
+ </const>
+ <const name="NoSymlinks" value="4">
+ <desc>Don't allow symbolic links as part of the path.</desc>
+ </const>
+ </enum>
+
+ <enum
+ name="ProcessCreateFlag"
+ uuid="35192799-bfde-405d-9bea-c735ab9998e4"
+ >
+ <desc>
+ Guest process execution flags.
</desc>
+
<const name="None" value="0">
<desc>No flag set.</desc>
</const>
+ <const name="WaitForProcessStartOnly" value="1">
+ <desc>Only use the specified timeout value to wait for starting the guest process - the guest
+ process itself then uses an infinite timeout.</desc>
+ </const>
+ <const name="IgnoreOrphanedProcesses" value="2">
+ <desc>Do not report an error when executed processes are still alive when VBoxService or the guest OS is shutting down.</desc>
+ </const>
+ <const name="Hidden" value="4">
+ <desc>Do not show the started process according to the guest OS guidelines.</desc>
+ </const>
+ <const name="NoProfile" value="8">
+ <desc>Do not use the user's profile data when exeuting a process. Only available for Windows guests.</desc>
+ </const>
+ <const name="WaitForStdOut" value="16">
+ <desc>The guest process waits until all data from stdout is read out.</desc>
+ </const>
+ <const name="WaitForStdErr" value="32">
+ <desc>The guest process waits until all data from stderr is read out.</desc>
+ </const>
+ <const name="ExpandArguments" value="64">
+ <desc>Expands environment variables in process arguments.</desc>
+ </const>
</enum>
<enum
- name="GuestDirEntryType"
- uuid="6d19d924-1b77-4fc8-b369-a3b2c85c8241"
+ name="ProcessPriority"
+ uuid="ee8cac50-e232-49fe-806b-d1214d9c2e49"
>
<desc>
- Guest directory entry type.
+ Process priorities.
</desc>
+
+ <const name="Invalid" value="0">
+ <desc>Invalid priority, do not use.</desc>
+ </const>
+ <const name="Default" value="1">
+ <desc>Default process priority determined by the OS.</desc>
+ </const>
+ </enum>
+
+ <enum
+ name="SymlinkType"
+ uuid="37794668-f8f1-4714-98a5-6f8fa2ed0118"
+ >
+ <desc>
+ Symbolic link types.
+ </desc>
+
<const name="Unknown" value="0">
- <desc>Unknown.</desc>
+ <desc>It is not known what is being targeted.</desc>
+ </const>
+ <const name="Directory" value="1">
+ <desc>The link targets a directory.</desc>
</const>
- <const name="Directory" value="4">
- <desc>Regular file.</desc>
+ <const name="File" value="2">
+ <desc>The link targets a file (or whatever else).</desc>
</const>
- <const name="File" value="10">
- <desc>Regular file.</desc>
+ </enum>
+
+ <enum
+ name="SymlinkReadFlag"
+ uuid="b7fe2b9d-790e-4b25-8adf-1ca33026931f"
+ >
+ <desc>
+ Symbolic link reading flags.
+ </desc>
+
+ <const name="None" value="0">
+ <desc>No flags set.</desc>
</const>
- <const name="Symlink" value="12">
- <desc>Symbolic link.</desc>
+ <const name="NoSymlinks" value="1">
+ <desc>Don't allow symbolic links as part of the path.</desc>
+ </const>
+ </enum>
+
+ <enum
+ name="ProcessStatus"
+ uuid="4d52368f-5b48-4bfe-b486-acf89139b52f"
+ >
+ <desc>
+ Process execution statuses.
+ </desc>
+ <const name="Undefined" value="0">
+ <desc>Process is in an undefined state.</desc>
+ </const>
+
+ <const name="Starting" value="10">
+ <desc>Process is being started.</desc>
+ </const>
+ <const name="Started" value="100">
+ <desc>Process has been started.</desc>
+ </const>
+ <const name="Paused" value="110">
+ <desc>Process has been paused.</desc>
+ </const>
+ <const name="Terminating" value="480">
+ <desc>Process is being terminated.</desc>
+ </const>
+ <const name="TerminatedNormally" value="500">
+ <desc>Process terminated normally.</desc>
+ </const>
+ <const name="TerminatedSignal" value="510">
+ <desc>Process terminated via signal.</desc>
+ </const>
+ <const name="TerminatedAbnormally" value="511">
+ <desc>Process terminated abnormally.</desc>
+ </const>
+ <const name="TimedOutKilled" value="512">
+ <desc>Process timed out and was killed.</desc>
+ </const>
+ <const name="TimedOutAbnormally" value="513">
+ <desc>Process timed out and was not killed successfully.</desc>
+ </const>
+ <const name="Down" value="600">
+ <desc>Service/OS is stopping, process was killed.</desc>
+ </const>
+ <const name="Error" value="800">
+ <desc>Something went wrong.</desc>
+ </const>
+ </enum>
+
+ <enum
+ name="FsObjType"
+ uuid="a1ed437c-b3c3-4ca2-b19c-4239d658d5e8"
+ >
+ <desc>
+ File system object type.
+ </desc>
+
+ <const name="Undefined" value="0">
+ <desc>Type is undefined / unknown.</desc>
+ </const>
+ <const name="FIFO" value="1">
+ <desc>Named pipe.</desc>
+ </const>
+ <const name="DevChar" value="10">
+ <desc>Character device.</desc>
+ </const>
+ <const name="DevBlock" value="11">
+ <desc>Block device.</desc>
+ </const>
+ <const name="Directory" value="50">
+ <desc>Directory.</desc>
+ </const>
+ <const name="File" value="80">
+ <desc>File.</desc>
+ </const>
+ <const name="Symlink" value="100">
+ <desc>Symlink.</desc>
+ </const>
+ <const name="Socket" value="200">
+ <desc>Socket.</desc>
+ </const>
+ <const name="Whiteout" value="400">
+ <desc>Whiteout.</desc>
+ </const>
+ </enum>
+
+ <enum
+ name="DragAndDropAction"
+ uuid="47f3b162-c107-4fcd-bfa7-54b8135c441e"
+ >
+ <desc>
+ Possible actions within an Drag and Drop operation.
+ </desc>
+
+ <const name="Ignore" value="0">
+ <desc>Do nothing.</desc>
+ </const>
+
+ <const name="Copy" value="1">
+ <desc>Copy the item to the target.</desc>
+ </const>
+
+ <const name="Move" value="2">
+ <desc>Move the item to the target.</desc>
+ </const>
+
+ <const name="Link" value="3">
+ <desc>Link the item from within the target.</desc>
+ </const>
+ </enum>
+
+ <enum
+ name="DirectoryOpenFlag"
+ uuid="5138837a-8fd2-4194-a1b0-08f7bc3949d0"
+ >
+ <desc>
+ Directory open flags.
+ </desc>
+ <const name="None" value="0">
+ <desc>No flag set.</desc>
+ </const>
+ <const name="NoSymlinks" value="1">
+ <desc>Don't allow symbolic links as part of the path.</desc>
</const>
</enum>
<interface
- name="IGuestDirEntry" extends="$unknown"
- uuid="20a66efc-c2f6-4438-826f-38454c04369e"
- wsmap="struct"
+ name="IGuestSession" extends="$unknown"
+ uuid="57eb82a8-822b-42c1-9d1c-5c54bc3d3250"
+ wsmap="managed"
>
<desc>
- Structure representing a directory entry on the guest OS.
+ A guest session represents one impersonated user account on the guest, so
+ every operation will use the same credentials specified when creating
+ the session object via <link to="IGuest::createSession"/>.
+
+ There can be a maximum of 32 sessions at once per VM. Each session keeps
+ track of its started guest processes, opened guest files or guest directories.
+ To work on guest files or directories a guest session offers methods to open
+ or create such objects (see <link to="IGuestSession::fileOpen"/> or
+ <link to="IGuestSession::directoryOpen"/> for example).
+
+ When done with either of these objects, including the guest session itself,
+ use the appropriate close() method to let the object do its cleanup work.
+
+ Every guest session has its own environment variable block which gets
+ automatically applied when starting a new guest process via
+ <link to="IGuestSession::processCreate"/> or <link to="IGuestSession::processCreateEx"/>.
+ To override (or unset) certain environment variables already set by the
+ guest session, one can specify a per-process environment block when using
+ one of the both above mentioned process creation calls.
</desc>
- <attribute name="nodeId" type="long long" readonly="yes">
- <desc>The unique identifier (within the guest's file system) of this file system object.</desc>
+
+ <attribute name="user" type="wstring" readonly="yes">
+ <desc>Returns the user name used by this session to impersonate
+ users on the guest.
+ </desc>
+ </attribute>
+
+ <attribute name="domain" type="wstring" readonly="yes">
+ <desc>Returns the domain name used by this session to impersonate
+ users on the guest.
+ </desc>
+ </attribute>
+
+ <attribute name="name" type="wstring" readonly="yes">
+ <desc>Returns the session's friendly name.</desc>
+ </attribute>
+
+ <attribute name="id" type="unsigned long" readonly="yes">
+ <desc>Returns the internal session ID.</desc>
+ </attribute>
+
+ <attribute name="timeout" type="unsigned long" readonly="no">
+ <desc>
+ Returns the session timeout (in ms).
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ </attribute>
+
+ <attribute name="environment" type="wstring" safearray="yes">
+ <desc>
+ Returns the current session environment.
+ </desc>
+ </attribute>
+
+ <attribute name="processes" type="IGuestProcess" readonly="yes" safearray="yes">
+ <desc>
+ Returns all current guest processes.
+ </desc>
+ </attribute>
+
+ <attribute name="directories" type="IGuestDirectory" readonly="yes" safearray="yes">
+ <desc>
+ Returns all currently opened guest directories.
+ </desc>
+ </attribute>
+
+ <attribute name="files" type="IGuestFile" readonly="yes" safearray="yes">
+ <desc>
+ Returns all currently opened guest files.
+ </desc>
+ </attribute>
+
+ <method name="close">
+ <desc>
+ Closes this session. All opened guest directories, files and
+ processes which are not referenced by clients anymore will be
+ uninitialized.
+ </desc>
+ </method>
+
+ <method name="copyFrom">
+ <desc>
+ Copies a file from guest to the host.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error starting the copy operation.
+ </result>
+ </desc>
+ <param name="source" type="wstring" dir="in">
+ <desc>Source file on the guest to copy to the host.</desc>
+ </param>
+ <param name="dest" type="wstring" dir="in">
+ <desc>Destination file name on the host.</desc>
+ </param>
+ <param name="flags" type="CopyFileFlag" dir="in" safearray="yes">
+ <desc>Copy flags; see <link to="CopyFileFlag"/> for more information.</desc>
+ </param>
+ <param name="progress" type="IProgress" dir="return">
+ <desc>Progress object to track the operation completion.</desc>
+ </param>
+ </method>
+
+ <method name="copyTo">
+ <desc>
+ Copies a file from host to the guest.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error starting the copy operation.
+ </result>
+ </desc>
+ <param name="source" type="wstring" dir="in">
+ <desc>Source file on the host to copy to the guest.</desc>
+ </param>
+ <param name="dest" type="wstring" dir="in">
+ <desc>Destination file name on the guest.</desc>
+ </param>
+ <param name="flags" type="CopyFileFlag" dir="in" safearray="yes">
+ <desc>Copy flags; see <link to="CopyFileFlag"/> for more information.</desc>
+ </param>
+ <param name="progress" type="IProgress" dir="return">
+ <desc>Progress object to track the operation completion.</desc>
+ </param>
+ </method>
+
+ <method name="directoryCreate">
+ <desc>
+ Create a directory on the guest.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while creating the directory.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Full path of directory to create.</desc>
+ </param>
+ <param name="mode" type="unsigned long" dir="in">
+ <desc>File creation mode.</desc>
+ </param>
+ <param name="flags" type="DirectoryCreateFlag" dir="in" safearray="yes">
+ <desc>Creation flags; see <link to="DirectoryCreateFlag"/> for more information.</desc>
+ </param>
+ </method>
+
+ <method name="directoryCreateTemp">
+ <desc>
+ Create a temporary directory on the guest.
+
+ <result name="VBOX_E_NOT_SUPPORTED">
+ The operation is not possible as requested on this particular
+ guest type.
+ </result>
+ <result name="E_INVALIDARG">
+ Invalid argument. This includes an incorrectly formatted template,
+ or a non-absolute path.
+ </result>
+ <result name="VBOX_E_IPRT_ERROR">
+ The temporary directory could not be created. Possible reasons
+ include a non-existing path or an insecure path when the secure
+ option was requested.
+ </result>
+ </desc>
+ <param name="templateName" type="wstring" dir="in">
+ <desc>Template for the name of the directory to create. This must
+ contain at least one 'X' character. The first group of consecutive
+ 'X' characters in the template will be replaced by a random
+ alphanumeric string to produce a unique name.</desc>
+ </param>
+ <param name="mode" type="unsigned long" dir="in">
+ <desc>The mode of the directory to create. Use 0700 unless there are
+ reasons not to. This parameter is ignored if "secure" is specified.
+ </desc>
+ </param>
+ <param name="path" type="wstring" dir="in">
+ <desc>The absolute path to create the temporary directory in.</desc>
+ </param>
+ <param name="secure" type="boolean" dir="in">
+ <desc>Whether to fail if the directory can not be securely created.
+ Currently this means that another unprivileged user cannot
+ manipulate the path specified or remove the temporary directory
+ after it has been created. Also causes the mode specified to be
+ ignored. May not be supported on all guest types.</desc>
+ </param>
+ <param name="directory" type="wstring" dir="return">
+ <desc>On success this will contain the name of the directory created
+ with full path.</desc>
+ </param>
+ </method>
+
+ <method name="directoryExists">
+ <desc>
+ Checks whether a directory exists on the guest or not.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while checking existence of the directory specified.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Directory to check existence for.</desc>
+ </param>
+ <param name="exists" type="boolean" dir="return">
+ <desc>Returns @c true if the directory exists, @c false if not.</desc>
+ </param>
+ </method>
+
+ <method name="directoryOpen">
+ <desc>
+ Opens a directory and creates a <link to="IGuestDirectory"/> object that
+ can be used for further operations.
+
+ <result name="VBOX_E_OBJECT_NOT_FOUND">
+ Directory to open was not found.
+ </result>
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while opening the directory.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Full path to file to open.</desc>
+ </param>
+ <param name="filter" type="wstring" dir="in">
+ <desc>Open filter to apply. This can include wildcards like ? and *.</desc>
+ </param>
+ <param name="flags" type="DirectoryOpenFlag" dir="in" safearray="yes">
+ <desc>Open flags; see <link to="DirectoryOpenFlag"/> for more information.</desc>
+ </param>
+ <param name="directory" type="IGuestDirectory" dir="return">
+ <desc><link to="IGuestDirectory"/> object containing the opened directory.</desc>
+ </param>
+ </method>
+
+ <method name="directoryQueryInfo">
+ <desc>
+ Queries information of a directory on the guest.
+
+ <result name="VBOX_E_OBJECT_NOT_FOUND">
+ Directory to query information for was not found.
+ </result>
+ <result name="VBOX_E_IPRT_ERROR">
+ Error querying information.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Directory to query information for.</desc>
+ </param>
+ <param name="info" type="IGuestFsObjInfo" dir="return">
+ <desc><link to="IGuestFsObjInfo"/> object containing the queried information.</desc>
+ </param>
+ </method>
+
+ <method name="directoryRemove">
+ <desc>
+ Removes a guest directory if not empty.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Full path of directory to remove.</desc>
+ </param>
+ </method>
+
+ <method name="directoryRemoveRecursive">
+ <desc>
+ Removes a guest directory recursively.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Full path of directory to remove recursively.</desc>
+ </param>
+ <param name="flags" type="DirectoryRemoveRecFlag" dir="in" safearray="yes">
+ <desc>Remove flags; see <link to="DirectoryRemoveRecFlag"/> for more information.</desc>
+ </param>
+ <param name="progress" type="IProgress" dir="return">
+ <desc>Progress object to track the operation completion.</desc>
+ </param>
+ </method>
+
+ <method name="directoryRename">
+ <desc>
+ Renames a directory on the guest.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="source" type="wstring" dir="in">
+ <desc>Source directory to rename.</desc>
+ </param>
+ <param name="dest" type="wstring" dir="in">
+ <desc>Destination directory to rename the source to.</desc>
+ </param>
+ <param name="flags" type="PathRenameFlag" dir="in" safearray="yes">
+ <desc>Rename flags; see <link to="PathRenameFlag"/> for more information.</desc>
+ </param>
+ </method>
+
+ <method name="directorySetACL">
+ <desc>
+ Sets the ACL (Access Control List) of a guest directory.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Full path of directory to set the ACL for.</desc>
+ </param>
+ <param name="acl" type="wstring" dir="in">
+ <desc>Actual ACL string to set. Must comply with the guest OS.</desc>
+ </param>
+ </method>
+
+ <method name="environmentClear">
+ <desc>
+ Clears (deletes) all session environment variables.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while clearing the session environment variables.
+ </result>
+ </desc>
+ </method>
+
+ <method name="environmentGet">
+ <desc>
+ Gets the value of a session environment variable.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while getting the value of the session environment variable.
+ </result>
+ </desc>
+ <param name="name" type="wstring" dir="in">
+ <desc>Name of session environment variable to get the value for.</desc>
+ </param>
+ <param name="value" type="wstring" dir="return">
+ <desc>
+ Value of the session environment variable specified. If this variable
+ does not exist and empty value will be returned.
+ </desc>
+ </param>
+ </method>
+
+ <method name="environmentSet">
+ <desc>
+ Sets a session environment variable.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while setting the session environment variable.
+ </result>
+ </desc>
+ <param name="name" type="wstring" dir="in">
+ <desc>Name of session environment variable to set.</desc>
+ </param>
+ <param name="value" type="wstring" dir="in">
+ <desc>Value to set the session environment variable to.</desc>
+ </param>
+ </method>
+
+ <method name="environmentUnset">
+ <desc>
+ Unsets session environment variable.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while unsetting the session environment variable.
+ </result>
+ </desc>
+ <param name="name" type="wstring" dir="in">
+ <desc>Name of session environment variable to unset (clear).</desc>
+ </param>
+ </method>
+
+ <method name="fileCreateTemp">
+ <desc>
+ Creates a temporary file on the guest.
+
+ <result name="VBOX_E_NOT_SUPPORTED">
+ The operation is not possible as requested on this particular
+ guest type.
+ </result>
+ <result name="E_INVALIDARG">
+ Invalid argument. This includes an incorrectly formatted template,
+ or a non-absolute path.
+ </result>
+ <result name="VBOX_E_IPRT_ERROR">
+ The temporary file could not be created. Possible reasons include
+ a non-existing path or an insecure path when the secure
+ option was requested.
+ </result>
+ </desc>
+ <param name="templateName" type="wstring" dir="in">
+ <desc>Template for the name of the file to create. This must contain
+ at least one 'X' character. The first group of consecutive 'X'
+ characters in the template will be replaced by a random
+ alphanumeric string to produce a unique name.
+ </desc>
+ </param>
+ <param name="mode" type="unsigned long" dir="in">
+ <desc>The mode of the file to create. Use 0700 unless there are
+ reasons not to. This parameter is ignored if "secure" is specified.
+ </desc>
+ </param>
+ <param name="path" type="wstring" dir="in">
+ <desc>The absolute path to create the temporary file in.</desc>
+ </param>
+ <param name="secure" type="boolean" dir="in">
+ <desc>Whether to fail if the file can not be securely created.
+ Currently this means that another unprivileged user cannot
+ manipulate the path specified or remove the temporary file after
+ it has been created. Also causes the mode specified to be ignored.
+ May not be supported on all guest types.</desc>
+ </param>
+ <param name="file" type="IGuestFile" dir="return">
+ <desc>On success this will contain an open file object for the new
+ temporary file.
+ </desc>
+ </param>
+ </method>
+
+ <method name="fileExists">
+ <desc>
+ Checks whether a file exists on the guest or not.
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while checking existence of the file specified.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>File to check existence for.</desc>
+ </param>
+ <param name="exists" type="boolean" dir="return">
+ <desc>Returns @c true if the file exists, @c false if not.</desc>
+ </param>
+ </method>
+
+ <method name="fileRemove">
+ <desc>
+ Removes a single file on the guest.
+
+ <result name="VBOX_E_OBJECT_NOT_FOUND">
+ File to remove was not found.
+ </result>
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while removing the file.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Path to the file to remove.</desc>
+ </param>
+ </method>
+
+ <method name="fileOpen">
+ <desc>
+ Opens a file and creates a <link to="IGuestFile"/> object that
+ can be used for further operations.
+
+ <result name="VBOX_E_OBJECT_NOT_FOUND">
+ File to open was not found.
+ </result>
+ <result name="VBOX_E_IPRT_ERROR">
+ Error while opening the file.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Full path to file to open.</desc>
+ </param>
+ <param name="openMode" type="wstring" dir="in">
+ <desc>The file open mode.</desc>
+ </param>
+ <param name="disposition" type="wstring" dir="in">
+ <desc>The file disposition.</desc>
+ </param>
+ <param name="creationMode" type="unsigned long" dir="in">
+ <desc>The file creation mode.</desc>
+ </param>
+ <param name="offset" type="long long" dir="in">
+ <desc>The initial read/write offset.</desc>
+ </param>
+ <param name="file" type="IGuestFile" dir="return">
+ <desc><link to="IGuestFile"/> object representing the opened file.</desc>
+ </param>
+ </method>
+
+ <method name="fileQueryInfo">
+ <desc>
+ Queries information of a file on the guest.
+
+ <result name="VBOX_E_OBJECT_NOT_FOUND">
+ File to query information for was not found.
+ </result>
+ <result name="VBOX_E_IPRT_ERROR">
+ Error querying information.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>File to query information for.</desc>
+ </param>
+ <param name="info" type="IGuestFsObjInfo" dir="return">
+ <desc><link to="IGuestFsObjInfo"/> object containing the queried information.</desc>
+ </param>
+ </method>
+
+ <method name="fileQuerySize">
+ <desc>
+ Queries the size of a file on the guest.
+
+ <result name="VBOX_E_OBJECT_NOT_FOUND">
+ File to rename was not found.
+ </result>
+ <result name="VBOX_E_IPRT_ERROR">
+ Error querying file size.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>File to query the size for.</desc>
+ </param>
+ <param name="size" type="long long" dir="return">
+ <desc>Queried file size.</desc>
+ </param>
+ </method>
+
+ <method name="fileRename">
+ <desc>
+ Renames a file on the guest.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="source" type="wstring" dir="in">
+ <desc>Source file to rename.</desc>
+ </param>
+ <param name="dest" type="wstring" dir="in">
+ <desc>Destination file to rename the source to.</desc>
+ </param>
+ <param name="flags" type="PathRenameFlag" dir="in" safearray="yes">
+ <desc>Rename flags; see <link to="PathRenameFlag"/> for more information.</desc>
+ </param>
+ </method>
+
+ <method name="fileSetACL">
+ <desc>
+ Sets the ACL (Access Control List) of a file on the guest.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="file" type="wstring" dir="in">
+ <desc>Full path of file to set the ACL for.</desc>
+ </param>
+ <param name="acl" type="wstring" dir="in">
+ <desc>Actual ACL string to set. Must comply with the guest OS.</desc>
+ </param>
+ </method>
+
+ <method name="processCreate">
+ <desc>
+ Executes an existing program inside the guest VM.
+
+ <note>
+ Starting at VirtualBox 4.2 guest process execution by default is limited
+ to serve up to 255 guest processes at a time. If all 255 guest processes
+ are still active and running, starting a new guest process will result in an
+ appropriate error message.
+
+ If ProcessCreateFlag_WaitForStdOut and / or respectively ProcessCreateFlag_WaitForStdErr
+ is / are set, the guest process will not exit until all data from the specified
+ stream(s) is / are read out.
+
+ To raise or lower the guest process execution limit, either the guest property
+ "/VirtualBox/GuestAdd/VBoxService/--control-procs-max-kept" or VBoxService'
+ command line by specifying "--control-procs-max-kept" needs to be modified.
+ A restart of the guest OS is required afterwards. To serve unlimited guest
+ processes, a value of "0" needs to be set (not recommended).
+ </note>
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Could not create process.
+ </result>
+ </desc>
+ <param name="command" type="wstring" dir="in">
+ <desc>
+ Full path name of the command to execute on the guest; the
+ commands has to exists in the guest VM in order to be executed.
+ </desc>
+ </param>
+ <param name="arguments" type="wstring" dir="in" safearray="yes">
+ <desc>Array of arguments passed to the execution command.</desc>
+ </param>
+ <param name="environment" type="wstring" dir="in" safearray="yes">
+ <desc>
+ Environment variables that can be set while the command is being
+ executed, in form of "NAME=VALUE"; one pair per entry. To unset a
+ variable just set its name ("NAME") without a value.
+
+ This parameter can be used to override environment variables set by
+ the guest session, which will be applied to the newly started process
+ in any case.
+ </desc>
+ </param>
+ <param name="flags" type="ProcessCreateFlag" dir="in" safearray="yes">
+ <desc>
+ Process creation flags;
+ see <link to="ProcessCreateFlag"/> for more information.
+ </desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="guestProcess" type="IGuestProcess" dir="return">
+ <desc>Guest process object of the newly created process.</desc>
+ </param>
+ </method>
+
+ <method name="processCreateEx">
+ <desc>
+ Executes an existing program inside the guest VM. Extended version for
+ also setting the process priority and affinity.
+
+ <note>
+ Starting at VirtualBox 4.2 guest process execution by default is limited
+ to serve up to 255 guest processes at a time. If all 255 guest processes
+ are still active and running, starting a new guest process will result in an
+ appropriate error message.
+
+ If ProcessCreateFlag_WaitForStdOut and / or respectively ProcessCreateFlag_WaitForStdErr
+ is / are set, the guest process will not exit until all data from the specified
+ stream(s) is / are read out.
+
+ To raise or lower the guest process execution limit, either the guest property
+ "/VirtualBox/GuestAdd/VBoxService/--control-procs-max-kept" or VBoxService'
+ command line by specifying "--control-procs-max-kept" needs to be modified.
+ A restart of the guest OS is required afterwards. To serve unlimited guest
+ processes, a value of "0" needs to be set (not recommended).
+ </note>
+
+ <result name="VBOX_E_IPRT_ERROR">
+ Could not create process.
+ </result>
+ </desc>
+ <param name="command" type="wstring" dir="in">
+ <desc>
+ Full path name of the command to execute on the guest; the
+ commands has to exists in the guest VM in order to be executed.
+ </desc>
+ </param>
+ <param name="arguments" type="wstring" dir="in" safearray="yes">
+ <desc>Array of arguments passed to the execution command.</desc>
+ </param>
+ <param name="environment" type="wstring" dir="in" safearray="yes">
+ <desc>
+ Environment variables that can be set while the command is being
+ executed, in form of "NAME=VALUE"; one pair per entry. To unset a
+ variable just set its name ("NAME") without a value.
+
+ This parameter can be used to override environment variables set by
+ the guest session, which will be applied to the newly started process
+ in any case.
+ </desc>
+ </param>
+ <param name="flags" type="ProcessCreateFlag" dir="in" safearray="yes">
+ <desc>
+ Process creation flags;
+ see <link to="ProcessCreateFlag"/> for more information.
+ </desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="priority" type="ProcessPriority" dir="in">
+ <desc>
+ Process priority to use for execution;
+ see see <link to="ProcessPriority"/> for more information.</desc>
+ </param>
+ <param name="affinity" type="long" dir="in" safearray="yes">
+ <desc>
+ Process affinity to use for execution. This parameter
+ is not implemented yet.
+ </desc>
+ </param>
+ <param name="guestProcess" type="IGuestProcess" dir="return">
+ <desc>Guest process object of the newly created process.</desc>
+ </param>
+ </method>
+
+ <method name="processGet">
+ <desc>
+ Gets a certain guest process by its process ID (PID).
+ </desc>
+ <param name="pid" type="unsigned long" dir="in">
+ <desc>Process ID (PID) to get guest process for.</desc>
+ </param>
+ <param name="guestProcess" type="IGuestProcess" dir="return">
+ <desc>Guest process of specified process ID (PID).</desc>
+ </param>
+ </method>
+
+ <method name="symlinkCreate">
+ <desc>
+ Creates a symbolic link on the guest.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="source" type="wstring" dir="in">
+ <desc>The name of the symbolic link.</desc>
+ </param>
+ <param name="target" type="wstring" dir="in">
+ <desc>The path to the symbolic link target.</desc>
+ </param>
+ <param name="type" type="SymlinkType" dir="in">
+ <desc>
+ The symbolic link type;
+ see <link to="SymlinkReadFlag"/> for more information.
+ </desc>
+ </param>
+ </method>
+
+ <method name="symlinkExists">
+ <desc>
+ Checks whether a symbolic link exists on the guest or not.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="symlink" type="wstring" dir="in">
+ <desc>Symbolic link to check existence for.</desc>
+ </param>
+ <param name="exists" type="boolean" dir="return">
+ <desc>Returns @c true if the symbolic link exists, @c false if not.</desc>
+ </param>
+ </method>
+
+ <method name="symlinkRead">
+ <desc>
+ Reads a symbolic link on the guest.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="symlink" type="wstring" dir="in">
+ <desc>Full path to symbolic link to read.</desc>
+ </param>
+ <param name="flags" type="SymlinkReadFlag" dir="in" safearray="yes">
+ <desc>
+ Read flags; see <link to="SymlinkReadFlag"/> for more information.
+ </desc>
+ </param>
+ <param name="target" type="wstring" dir="return">
+ <desc>
+ Target of the symbolic link pointing to, if found.
+ </desc>
+ </param>
+ </method>
+
+ <method name="symlinkRemoveDirectory">
+ <desc>
+ Removes a symbolic link on the guest if it's a directory.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="path" type="wstring" dir="in">
+ <desc>Symbolic link to remove.</desc>
+ </param>
+ </method>
+
+ <method name="symlinkRemoveFile">
+ <desc>
+ Removes a symbolic link on the guest if it's a file.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="file" type="wstring" dir="in">
+ <desc>Symbolic link to remove.</desc>
+ </param>
+ </method>
+
+ </interface>
+
+ <interface
+ name="IProcess" extends="$unknown"
+ uuid="08864d56-96ab-418b-adbc-5a679532aeb0"
+ wsmap="managed"
+ >
+ <desc>
+ Abstract parent interface for processes handled by VirtualBox.
+ </desc>
+ <attribute name="PID" type="unsigned long" readonly="yes">
+ <desc>
+ The process ID (PID).
+ </desc>
+ </attribute>
+ <attribute name="status" type="ProcessStatus" readonly="yes">
+ <desc>
+ The current process status; see <link to="ProcessStatus"/>
+ for more information.
+ </desc>
+ </attribute>
+ <attribute name="exitCode" type="long" readonly="yes">
+ <desc>
+ The exit code. Only available when the process has been
+ terminated normally.
+ </desc>
+ </attribute>
+ <attribute name="environment" type="wstring" readonly="yes" safearray="yes">
+ <desc>
+ The environment block this process is using during execution.
+ </desc>
+ </attribute>
+ <attribute name="arguments" type="wstring" readonly="yes" safearray="yes">
+ <desc>
+ The arguments this process is using for execution.
+ </desc>
+ </attribute>
+ <attribute name="executablePath" type="wstring" readonly="yes">
+ <desc>Full path of the actual executable image.</desc>
</attribute>
<attribute name="name" type="wstring" readonly="yes">
- <desc>The filename.</desc>
+ <desc>The friendly name of this process.</desc>
</attribute>
- <attribute name="type" type="GuestDirEntryType" readonly="yes">
- <desc>The entry type.</desc>
+
+ <method name="waitFor">
+ <desc>
+ Waits for one more events to happen.
+ </desc>
+ <param name="waitFor" type="unsigned long" dir="in">
+ <desc>
+ Specifies what to wait for;
+ see <link to="ProcessWaitForFlag"/> for more information.
+ </desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="reason" type="ProcessWaitResult" dir="return">
+ <desc>
+ The overall wait result;
+ see <link to="ProcessWaitResult"/> for more information.
+ </desc>
+ </param>
+ </method>
+
+ <method name="waitForArray">
+ <desc>
+ Waits for one more events to happen.
+ Scriptable version of <link to="#waitFor" />.
+ </desc>
+ <param name="waitFor" type="ProcessWaitForFlag" dir="in" safearray="yes">
+ <desc>
+ Specifies what to wait for;
+ see <link to="ProcessWaitForFlag"/> for more information.
+ </desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="reason" type="ProcessWaitResult" dir="return">
+ <desc>
+ The overall wait result;
+ see <link to="ProcessWaitResult"/> for more information.
+ </desc>
+ </param>
+ </method>
+
+ <method name="read">
+ <desc>
+ Reads data from a running process.
+ </desc>
+ <param name="handle" type="unsigned long" dir="in">
+ <desc>Handle to read from. Usually 0 is stdin.</desc>
+ </param>
+ <param name="toRead" type="unsigned long" dir="in">
+ <desc>Number of bytes to read.</desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="data" type="octet" dir="return" safearray="yes">
+ <desc>Array of data read.</desc>
+ </param>
+ </method>
+
+ <method name="write">
+ <desc>
+ Writes data to a running process.
+ </desc>
+ <param name="handle" type="unsigned long" dir="in">
+ <desc>Handle to write to. Usually 0 is stdin, 1 is stdout and 2 is stderr.</desc>
+ </param>
+ <param name="flags" type="unsigned long" dir="in">
+ <desc>
+ A combination of <link to="ProcessInputFlag"/> flags.
+ </desc>
+ </param>
+ <param name="data" type="octet" dir="in" safearray="yes">
+ <desc>
+ Array of bytes to write. The size of the array also specifies
+ how much to write.
+ </desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="written" type="unsigned long" dir="return">
+ <desc>How much bytes were written.</desc>
+ </param>
+ </method>
+
+ <method name="writeArray">
+ <desc>
+ Writes data to a running process.
+ Scriptable version of <link to="#write" />.
+ </desc>
+ <param name="handle" type="unsigned long" dir="in">
+ <desc>Handle to write to. Usually 0 is stdin, 1 is stdout and 2 is stderr.</desc>
+ </param>
+ <param name="flags" type="ProcessInputFlag" dir="in" safearray="yes">
+ <desc>
+ A combination of <link to="ProcessInputFlag"/> flags.
+ </desc>
+ </param>
+ <param name="data" type="octet" dir="in" safearray="yes">
+ <desc>
+ Array of bytes to write. The size of the array also specifies
+ how much to write.
+ </desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="written" type="unsigned long" dir="return">
+ <desc>How much bytes were written.</desc>
+ </param>
+ </method>
+
+ <method name="terminate">
+ <desc>
+ Terminates (kills) a running process.
+ </desc>
+ </method>
+ </interface>
+
+ <interface
+ name="IGuestProcess" extends="IProcess"
+ uuid="dfa39a36-5d43-4840-a025-67ea956b3111"
+ wsmap="managed"
+ >
+ <desc>
+ Implementation of the <link to="IProcess" /> object
+ for processes on the guest.
+ </desc>
+ </interface>
+
+ <interface
+ name="IDirectory" extends="$unknown"
+ uuid="1b70dd03-26d7-483a-8877-89bbb0f87b70"
+ wsmap="managed"
+ >
+ <desc>
+ Abstract parent interface for directories handled by VirtualBox.
+ </desc>
+
+ <attribute name="directoryName" type="wstring" readonly="yes">
+ <desc>
+ Full path of directory.
+ </desc>
+ </attribute>
+
+ <attribute name="filter" type="wstring" readonly="yes">
+ <desc>
+ The open filter.
+ </desc>
</attribute>
+
+ <method name="close">
+ <desc>
+ Closes this directory. After closing operations like reading the next
+ directory entry will not be possible anymore.
+ </desc>
+ </method>
+
+ <method name="read">
+ <desc>
+ Reads the next directory entry of this directory.
+ <result name="VBOX_E_OBJECT_NOT_FOUND">
+ No more directory entries to read.
+ </result>
+ </desc>
+ <param name="objInfo" type="IFsObjInfo" dir="return">
+ <desc>Object information of the current directory entry read. Also see <link to="IFsObjInfo"/>.</desc>
+ </param>
+ </method>
+ </interface>
+
+ <interface
+ name="IGuestDirectory" extends="IDirectory"
+ uuid="af4a8ce0-0725-42b7-8826-46e3c7ba7357"
+ wsmap="managed"
+ >
+ <desc>
+ Implementation of the <link to="IDirectory" /> object
+ for directories on the guest.
+ </desc>
+ </interface>
+
+ <interface
+ name="IFile" extends="$unknown"
+ uuid="b702a560-6139-4a8e-a892-bbf14b97bf97"
+ wsmap="managed"
+ >
+ <desc>
+ Abstract parent interface for files handled by VirtualBox.
+ </desc>
+ <attribute name="creationMode" type="unsigned long" readonly="yes">
+ <desc>
+ The creation mode.
+ </desc>
+ </attribute>
+ <attribute name="disposition" type="unsigned long" readonly="yes">
+ <desc>
+ The disposition mode.
+ </desc>
+ </attribute>
+ <attribute name="fileName" type="wstring" readonly="yes">
+ <desc>
+ Full path of the actual file name of this file.
+ </desc>
+ </attribute>
+ <attribute name="initialSize" type="long long" readonly="yes">
+ <desc>
+ The initial size in bytes when opened.
+ </desc>
+ </attribute>
+ <attribute name="openMode" type="unsigned long" readonly="yes">
+ <desc>
+ The open mode.
+ </desc>
+ </attribute>
+ <attribute name="offset" type="long long" readonly="yes">
+ <desc>
+ Current read/write offset in bytes.
+ </desc>
+ </attribute>
+
+ <method name="close">
+ <desc>
+ Closes this file. After closing operations like reading data,
+ writing data or querying information will not be possible anymore.
+ </desc>
+ </method>
+
+ <method name="queryInfo">
+ <desc>
+ Queries information about this file.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="objInfo" type="IFsObjInfo" dir="return">
+ <desc>Object information of this file. Also see <link to="IFsObjInfo"/>.</desc>
+ </param>
+ </method>
+
+ <method name="read">
+ <desc>
+ Reads data from this file.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="toRead" type="unsigned long" dir="in">
+ <desc>Number of bytes to read.</desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="data" type="octet" dir="return" safearray="yes">
+ <desc>Array of data read.</desc>
+ </param>
+ </method>
+
+ <method name="readAt">
+ <desc>
+ Reads data from an offset of this file.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="offset" type="long long" dir="in">
+ <desc>Offset in bytes to start reading.</desc>
+ </param>
+ <param name="toRead" type="unsigned long" dir="in">
+ <desc>Number of bytes to read.</desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="data" type="octet" dir="return" safearray="yes">
+ <desc>Array of data read.</desc>
+ </param>
+ </method>
+
+ <method name="seek">
+ <desc>
+ Changes the read and write position of this file.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="offset" type="long long" dir="in">
+ <desc>Offset to seek.</desc>
+ </param>
+ <param name="whence" type="FileSeekType" dir="in">
+ <desc>
+ Seek mode; see <link to="FileSeekType"/> for more information.
+ </desc>
+ </param>
+ </method>
+
+ <method name="setACL">
+ <desc>
+ Sets the ACL of this file.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="acl" type="wstring" dir="in">
+ <desc>ACL string to set.</desc>
+ </param>
+ </method>
+
+ <method name="write">
+ <desc>
+ Writes bytes to this file.
+ </desc>
+ <param name="data" type="octet" dir="in" safearray="yes">
+ <desc>
+ Array of bytes to write. The size of the array also specifies
+ how much to write.
+ </desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="written" type="unsigned long" dir="return">
+ <desc>How much bytes were written.</desc>
+ </param>
+ </method>
+
+ <method name="writeAt">
+ <desc>
+ Writes bytes at a certain offset to this file.
+
+ <result name="E_NOTIMPL">
+ The method is not implemented yet.
+ </result>
+ </desc>
+ <param name="offset" type="long long" dir="in">
+ <desc>Offset in bytes to start writing.</desc>
+ </param>
+ <param name="data" type="octet" dir="in" safearray="yes">
+ <desc>
+ Array of bytes to write. The size of the array also specifies
+ how much to write.
+ </desc>
+ </param>
+ <param name="timeoutMS" type="unsigned long" dir="in">
+ <desc>
+ Timeout (in ms) to wait for the operation to complete.
+ Pass 0 for an infinite timeout.
+ </desc>
+ </param>
+ <param name="written" type="unsigned long" dir="return">
+ <desc>How much bytes were written.</desc>
+ </param>
+ </method>
+
+ </interface>
+
+ <interface
+ name="IGuestFile" extends="IFile"
+ uuid="60661aec-145f-4d11-b80e-8ea151598093"
+ wsmap="managed"
+ >
+ <desc>
+ Implementation of the <link to="IFile" /> object
+ for files on the guest.
+ </desc>
+ </interface>
+
+ <interface
+ name="IFsObjInfo" extends="$unknown"
+ uuid="4047ba30-7006-4966-ae86-94164e5e20eb"
+ wsmap="managed"
+ >
+ <desc>
+ Abstract parent interface for VirtualBox file system object information.
+ This can be information about a file or a directory, for example.
+ </desc>
+
+ <attribute name="accessTime" type="long long" readonly="yes">
+ <desc>
+ Time of last access (st_atime).
+ </desc>
+ </attribute>
+ <attribute name="allocatedSize" type="long long" readonly="yes">
+ <desc>
+ Disk allocation size (st_blocks * DEV_BSIZE).
+ </desc>
+ </attribute>
+ <attribute name="birthTime" type="long long" readonly="yes">
+ <desc>
+ Time of file birth (st_birthtime).
+ </desc>
+ </attribute>
+ <attribute name="changeTime" type="long long" readonly="yes">
+ <desc>
+ Time of last status change (st_ctime).
+ </desc>
+ </attribute>
+ <attribute name="deviceNumber" type="unsigned long" readonly="yes">
+ <desc>
+ The device number of a character or block device type object (st_rdev).
+ </desc>
+ </attribute>
+ <attribute name="fileAttributes" type="wstring" readonly="yes">
+ <desc>
+ File attributes. Not implemented yet.
+ </desc>
+ </attribute>
+ <attribute name="generationId" type="unsigned long" readonly="yes">
+ <desc>
+ The current generation number (st_gen).
+ </desc>
+ </attribute>
+ <attribute name="GID" type="unsigned long" readonly="yes">
+ <desc>
+ The group the filesystem object is assigned (st_gid).
+ </desc>
+ </attribute>
+ <attribute name="groupName" type="wstring" readonly="yes">
+ <desc>
+ The group name.
+ </desc>
+ </attribute>
+ <attribute name="hardLinks" type="unsigned long" readonly="yes">
+ <desc>
+ Number of hard links to this filesystem object (st_nlink).
+ </desc>
+ </attribute>
+ <attribute name="modificationTime" type="long long" readonly="yes">
+ <desc>
+ Time of last data modification (st_mtime).
+ </desc>
+ </attribute>
+ <attribute name="name" type="wstring" readonly="yes">
+ <desc>
+ The object's name.
+ </desc>
+ </attribute>
+ <attribute name="nodeId" type="long long" readonly="yes">
+ <desc>
+ The unique identifier (within the filesystem) of this filesystem object (st_ino).
+ </desc>
+ </attribute>
+ <attribute name="nodeIdDevice" type="unsigned long" readonly="yes">
+ <desc>
+ The device number of the device which this filesystem object resides on (st_dev).
+ </desc>
+ </attribute>
+ <attribute name="objectSize" type="long long" readonly="yes">
+ <desc>
+ The logical size (st_size). For normal files this is the size of the file.
+ For symbolic links, this is the length of the path name contained in the
+ symbolic link. For other objects this fields needs to be specified.
+ </desc>
+ </attribute>
+ <attribute name="type" type="FsObjType" readonly="yes">
+ <desc>
+ The object type. See <link to="FsObjType" /> for more.
+ </desc>
+ </attribute>
+ <attribute name="UID" type="unsigned long" readonly="yes">
+ <desc>
+ The user owning the filesystem object (st_uid).
+ </desc>
+ </attribute>
+ <attribute name="userFlags" type="unsigned long" readonly="yes">
+ <desc>
+ User flags (st_flags).
+ </desc>
+ </attribute>
+ <attribute name="userName" type="wstring" readonly="yes">
+ <desc>
+ The user name.
+ </desc>
+ </attribute>
+
+ </interface>
+
+ <interface
+ name="IGuestFsObjInfo" extends="IFsObjInfo"
+ uuid="d5cf678e-3484-4e4a-ac55-329e15462e18"
+ wsmap="managed"
+ >
+ <desc>
+ Represents the guest implementation of the
+ <link to="IFsObjInfo" /> object.
+ </desc>
</interface>
<interface
name="IGuest" extends="$unknown"
- uuid="ed109b6e-0578-4b17-8ace-52646789f1a0"
+ uuid="19c32350-0618-4ede-b0c3-2b4311bf0d9b"
wsmap="managed"
>
<desc>
@@ -8660,9 +10746,16 @@
<attribute name="additionsVersion" type="wstring" readonly="yes">
<desc>
- Version of the Guest Additions including the revision (3 decimal numbers
- separated by dots + revision number) installed on the guest or empty
- when the Additions are not installed.
+ Version of the Guest Additions in the same format as
+ <link to="IVirtualBox::version"/>.
+ </desc>
+ </attribute>
+
+ <attribute name="additionsRevision" type="unsigned long" readonly="yes">
+ <desc>
+ The internal build revision number of the additions.
+
+ See also <link to="IVirtualBox::revision"/>.
</desc>
</attribute>
@@ -8673,6 +10766,10 @@
</desc>
</attribute>
+ <attribute name="sessions" type="IGuestSession" readonly="yes" safearray="yes">
+ <desc>Returns a collection of all opened guest sessions.</desc>
+ </attribute>
+
<attribute name="memoryBalloonSize" type="unsigned long">
<desc>Guest system memory balloon size in megabytes (transient property).</desc>
</attribute>
@@ -8789,482 +10886,316 @@
</param>
</method>
- <method name="executeProcess">
+ <method name="dragHGEnter">
<desc>
- Executes an existing program inside the guest VM.
+ Informs the guest about a Drag and Drop enter event.
- <note>
- Starting at VirtualBox 4.1.8 guest process execution by default is limited
- to serve up to 25 guest processes at a time. If all 25 guest processes
- are still active and running, starting a new guest process will result in an
- appropriate error message.
-
- If ExecuteProcessFlag_WaitForStdOut and/or respectively
- ExecuteProcessFlag_WaitForStdErr of <link to="ExecuteProcessFlag"/> is
- set, the guest process will not exit until all data from the specified
- stream(s) is/are read out.
-
- To raise or lower the guest process execution limit, either the guest property
- "/VirtualBox/GuestAdd/VBoxService/--control-procs-max-kept" or VBoxService'
- command line by specifying "--control-procs-max-kept" needs to be modified.
- A restart of the guest OS is required afterwards. To serve unlimited guest
- processes, a value of "0" needs to be set (not recommended).
- </note>
+ This is used in Host - Guest direction.
- <result name="VBOX_E_IPRT_ERROR">
- Could not execute process.
+ <result name="VBOX_E_VM_ERROR">
+ VMM device is not available.
</result>
</desc>
- <param name="execName" type="wstring" dir="in">
- <desc>
- Full path name of the command to execute on the guest; the
- commands has to exists in the guest VM in order to be executed.
- </desc>
+ <param name="screenId" type="unsigned long" dir="in">
+ <desc>The screen id where the Drag and Drop event occured.</desc>
</param>
- <param name="flags" type="unsigned long" dir="in">
- <desc>
- <link to="ExecuteProcessFlag"/> flags.
- </desc>
+ <param name="y" type="unsigned long" dir="in">
+ <desc>y-position of the event.</desc>
</param>
- <param name="arguments" type="wstring" safearray="yes" dir="in">
- <desc>
- Array of arguments passed to the execution command.
- </desc>
+ <param name="x" type="unsigned long" dir="in">
+ <desc>x-position of the event.</desc>
</param>
- <param name="environment" type="wstring" safearray="yes" dir="in">
- <desc>
- Environment variables that can be set while the command is being
- executed, in form of "NAME=VALUE"; one pair per entry. To unset a
- variable just set its name ("NAME") without a value.
- </desc>
+ <param name="defaultAction" type="DragAndDropAction" dir="in">
+ <desc>The default action to use.</desc>
</param>
- <param name="userName" type="wstring" dir="in">
- <desc>
- User name under which the command will be executed; has to exist
- and have the appropriate rights to execute programs in the VM.
- </desc>
+ <param name="allowedActions" type="DragAndDropAction" dir="in" safearray="yes">
+ <desc>The actions which are allowed.</desc>
</param>
- <param name="password" type="wstring" dir="in">
- <desc>
- Password of the user account specified.
- </desc>
+ <param name="formats" type="wstring" dir="in" safearray="yes">
+ <desc>The supported mime types.</desc>
</param>
- <param name="timeoutMS" type="unsigned long" dir="in">
- <desc>
- The maximum timeout value (in msec) to wait for finished program
- execution. Pass 0 for an infinite timeout.
- </desc>
- </param>
- <param name="pid" type="unsigned long" dir="out">
- <desc>
- The PID (process ID) of the started command for later reference.
- </desc>
- </param>
- <param name="progress" type="IProgress" dir="return">
- <desc>Progress object to track the operation completion.</desc>
+ <param name="resultAction" type="DragAndDropAction" dir="return">
+ <desc>The resulting action of this event.</desc>
</param>
</method>
- <method name="getProcessOutput">
+ <method name="dragHGMove">
<desc>
- Retrieves output of a formerly started and running guest process.
+ Informs the guest about a Drag and Drop move event.
- <note>
- Starting with VirtualBox 4.1.8 this only will return output data
- from stdout or stderr if flag ExecuteProcessFlag_WaitForStdOut
- and/or respectively ExecuteProcessFlag_WaitForStdErr of
- <link to="ExecuteProcessFlag"/> is set in the
- former <link to="#executeProcess"/> call for this guest process.
- </note>
+ This is used in Host - Guest direction.
- <result name="VBOX_E_IPRT_ERROR">
- Could not retrieve output.
+ <result name="VBOX_E_VM_ERROR">
+ VMM device is not available.
</result>
</desc>
- <param name="pid" type="unsigned long" dir="in">
- <desc>
- Process id returned by earlier <link to="#executeProcess"/> call.
- </desc>
+ <param name="screenId" type="unsigned long" dir="in">
+ <desc>The screen id where the Drag and Drop event occured.</desc>
</param>
- <param name="flags" type="unsigned long" dir="in">
- <desc>
- <link to="ProcessOutputFlag"/> flags.
- </desc>
+ <param name="x" type="unsigned long" dir="in">
+ <desc>x-position of the event.</desc>
</param>
- <param name="timeoutMS" type="unsigned long" dir="in">
- <desc>
- The maximum timeout value (in msec) to wait for output
- data. Pass 0 for an infinite timeout.
- </desc>
+ <param name="y" type="unsigned long" dir="in">
+ <desc>y-position of the event.</desc>
</param>
- <param name="size" type="long long" dir="in">
- <desc>
- Size in bytes to read in the buffer.
- </desc>
+ <param name="defaultAction" type="DragAndDropAction" dir="in">
+ <desc>The default action to use.</desc>
</param>
- <param name="data" type="octet" safearray="yes" dir="return">
- <desc>
- Buffer for retrieving the actual output. A data size of 0 means end of file
- if the requested size was not 0. This is the unprocessed
- output data, i.e. the line ending style depends on the platform of
- the system the server is running on.
- </desc>
+ <param name="allowedActions" type="DragAndDropAction" dir="in" safearray="yes">
+ <desc>The actions which are allowed.</desc>
+ </param>
+ <param name="formats" type="wstring" dir="in" safearray="yes">
+ <desc>The supported mime types.</desc>
+ </param>
+ <param name="resultAction" type="DragAndDropAction" dir="return">
+ <desc>The resulting action of this event.</desc>
</param>
</method>
- <method name="getProcessStatus">
+ <method name="dragHGLeave">
<desc>
- Retrieves status, exit code and the exit reason of a formerly started
- guest process. If a guest process exited or got terminated this function
- returns its final status and removes this process from the list of
- known guest processes for further retrieval.
+ Informs the guest about a Drag and Drop leave event.
- <result name="VBOX_E_IPRT_ERROR">
- Process with specified PID was not found.
+ This is used in Host - Guest direction.
+
+ <result name="VBOX_E_VM_ERROR">
+ VMM device is not available.
</result>
</desc>
- <param name="pid" type="unsigned long" dir="in">
- <desc>
- Process id returned by earlier <link to="#executeProcess"/> call.
- </desc>
- </param>
- <param name="exitcode" type="unsigned long" dir="out">
- <desc>
- The exit code (if available).
- </desc>
- </param>
- <param name="flags" type="unsigned long" dir="out">
- <desc>
- Additional flags of process status. Not used at the moment and
- must be set to 0.
- </desc>
- </param>
- <param name="reason" type="ExecuteProcessStatus" dir="return">
- <desc>
- The current process status.
- </desc>
+ <param name="screenId" type="unsigned long" dir="in">
+ <desc>The screen id where the Drag and Drop event occured.</desc>
</param>
</method>
- <method name="copyFromGuest">
+ <method name="dragHGDrop">
<desc>
- Copies files/directories from guest to the host.
+ Informs the guest about a drop event.
- <result name="VBOX_E_IPRT_ERROR">
- Error while copying.
+ This is used in Host - Guest direction.
+
+ <result name="VBOX_E_VM_ERROR">
+ VMM device is not available.
</result>
</desc>
- <param name="source" type="wstring" dir="in">
- <desc>
- Source file on the guest to copy.
- </desc>
+ <param name="screenId" type="unsigned long" dir="in">
+ <desc>The screen id where the Drag and Drop event occured.</desc>
</param>
- <param name="dest" type="wstring" dir="in">
- <desc>
- Destination path on the host.
- </desc>
+ <param name="x" type="unsigned long" dir="in">
+ <desc>x-position of the event.</desc>
</param>
- <param name="userName" type="wstring" dir="in">
- <desc>
- User name under which the copy command will be executed; the
- user has to exist and have the appropriate rights to read from
- the source path.
- </desc>
+ <param name="y" type="unsigned long" dir="in">
+ <desc>y-position of the event.</desc>
</param>
- <param name="password" type="wstring" dir="in">
- <desc>
- Password of the user account specified.
- </desc>
+ <param name="defaultAction" type="DragAndDropAction" dir="in">
+ <desc>The default action to use.</desc>
</param>
- <param name="flags" type="unsigned long" dir="in">
- <desc>
- <link to="CopyFileFlag"/> flags. Not used at the moment and should be set to 0.
- </desc>
+ <param name="allowedActions" type="DragAndDropAction" dir="in" safearray="yes">
+ <desc>The actions which are allowed.</desc>
</param>
- <param name="progress" type="IProgress" dir="return">
- <desc>Progress object to track the operation completion.</desc>
+ <param name="formats" type="wstring" dir="in" safearray="yes">
+ <desc>The supported mime types.</desc>
+ </param>
+ <param name="format" type="wstring" dir="out">
+ <desc>The resulting format of this event.</desc>
+ </param>
+ <param name="resultAction" type="DragAndDropAction" dir="return">
+ <desc>The resulting action of this event.</desc>
</param>
</method>
- <method name="copyToGuest">
+ <method name="dragHGPutData">
<desc>
- Copies files/directories from host to the guest.
+ Informs the guest about a drop data event.
- <result name="VBOX_E_IPRT_ERROR">
- Error while copying.
+ This is used in Host - Guest direction.
+
+ <result name="VBOX_E_VM_ERROR">
+ VMM device is not available.
</result>
</desc>
- <param name="source" type="wstring" dir="in">
- <desc>
- Source file on the host to copy.
- </desc>
- </param>
- <param name="dest" type="wstring" dir="in">
- <desc>
- Destination path on the guest.
- </desc>
- </param>
- <param name="userName" type="wstring" dir="in">
- <desc>
- User name under which the copy command will be executed; the
- user has to exist and have the appropriate rights to write to
- the destination path.
- </desc>
+ <param name="screenId" type="unsigned long" dir="in">
+ <desc>The screen id where the Drag and Drop event occured.</desc>
</param>
- <param name="password" type="wstring" dir="in">
- <desc>
- Password of the user account specified.
- </desc>
+ <param name="format" type="wstring" dir="in">
+ <desc>The mime type the data is in.</desc>
</param>
- <param name="flags" type="unsigned long" dir="in">
- <desc>
- <link to="CopyFileFlag"/> flags. Not used at the moment and should be set to 0.
- </desc>
+ <param name="data" type="octet" dir="in" safearray="yes">
+ <desc>The actual data.</desc>
</param>
<param name="progress" type="IProgress" dir="return">
<desc>Progress object to track the operation completion.</desc>
</param>
</method>
- <method name="directoryClose">
+ <method name="dragGHPending">
<desc>
- Closes a formerly opened guest directory.
+ Ask the guest if there is any Drag and Drop operation pending in the guest.
- <result name="VBOX_E_IPRT_ERROR">
- Error while closing directory.
- </result>
+ If no Drag and Drop operation is pending currently, Ignore is returned.
- </desc>
- <param name="handle" type="unsigned long" dir="in">
- <desc>
- Handle of opened directory to close.
- </desc>
- </param>
- </method>
-
- <method name="directoryCreate">
- <desc>
- Creates a directory on the guest.
+ This is used in Guest - Host direction.
- <result name="VBOX_E_IPRT_ERROR">
- Error while creating directory.
+ <result name="VBOX_E_VM_ERROR">
+ VMM device is not available.
</result>
</desc>
- <param name="directory" type="wstring" dir="in">
- <desc>
- Directory to create.
- </desc>
- </param>
- <param name="userName" type="wstring" dir="in">
- <desc>
- User name under which the directory creation will be executed; the
- user has to exist and have the appropriate rights to create the
- desired directory.
- </desc>
+ <param name="screenId" type="unsigned long" dir="in">
+ <desc>The screen id where the Drag and Drop event occured.</desc>
</param>
- <param name="password" type="wstring" dir="in">
- <desc>
- Password of the user account specified.
- </desc>
+ <param name="format" type="wstring" dir="out" safearray="yes">
+ <desc>On return the supported mime types.</desc>
</param>
- <param name="mode" type="unsigned long" dir="in">
- <desc>
- File mode.
- </desc>
+ <param name="allowedActions" type="DragAndDropAction" dir="out" safearray="yes">
+ <desc>On return the actions which are allowed.</desc>
</param>
- <param name="flags" type="unsigned long" dir="in">
- <desc>
- <link to="DirectoryCreateFlag"/> flags.
- </desc>
+ <param name="defaultAction" type="DragAndDropAction" dir="return">
+ <desc>On return the default action to use.</desc>
</param>
</method>
- <method name="directoryOpen">
+ <method name="dragGHDropped">
<desc>
- Opens a directory on the guest.
+ Informs the guest that a drop event occured for a pending Drag and Drop event.
- <result name="VBOX_E_IPRT_ERROR">
- Error while opening / reading directory.
+ This is used in Guest - Host direction.
+
+ <result name="VBOX_E_VM_ERROR">
+ VMM device is not available.
</result>
</desc>
- <param name="directory" type="wstring" dir="in">
- <desc>
- Directory to read.
- </desc>
- </param>
- <param name="filter" type="wstring" dir="in">
- <desc>
- Directory filter (DOS style wildcards). Set to empty
- string if no filter required.
- </desc>
- </param>
- <param name="flags" type="unsigned long" dir="in">
- <desc>
- <link to="DirectoryOpenFlag"/> flags.
- </desc>
+
+ <param name="format" type="wstring" dir="in">
+ <desc>The mime type the data must be in.</desc>
</param>
- <param name="userName" type="wstring" dir="in">
- <desc>
- User name under which the directory reading will be performed; the
- user has to exist and have the appropriate rights to access / read the
- desired directory.
- </desc>
+ <param name="action" type="DragAndDropAction" dir="in">
+ <desc>The action to use.</desc>
</param>
- <param name="password" type="wstring" dir="in">
- <desc>
- Password of the user account specified.
- </desc>
- </param>
- <param name="handle" type="unsigned long" dir="return">
- <desc>
- Handle of opened directory returned by openDirectory.
- </desc>
+ <param name="progress" type="IProgress" dir="return">
+ <desc>Progress object to track the operation completion.</desc>
</param>
</method>
- <method name="directoryRead">
+ <method name="dragGHGetData">
<desc>
- Reads the next directory entry of an opened guest directory.
+ Fetch the data of a previously Drag and Drop event from the guest.
- <result name="E_ABORT">
- When the end of the directory has been reached.
- </result>
+ This is used in Guest - Host direction.
- <result name="VBOX_E_IPRT_ERROR">
- Error while opening / reading directory.
+ <result name="VBOX_E_VM_ERROR">
+ VMM device is not available.
</result>
</desc>
- <param name="handle" type="unsigned long" dir="in">
- <desc>
- Handle of opened directory returned by openDirectory.
- </desc>
- </param>
- <param name="entry" type="IGuestDirEntry" dir="return">
- <desc>
- Information about next directory entry on success.
- </desc>
+
+ <param name="data" type="octet" safearray="yes" dir="return">
+ <desc>The actual data.</desc>
</param>
</method>
- <method name="fileExists">
+ <method name="createSession">
<desc>
- Checks if the specified file name exists and is a regular file.
+ Creates a new guest session for controlling the guest.
- If the file name ends with a slash or backslash, the function assumes
- it's a directory and will check if the specified directory exists and
- is a regular directory.
+ A guest session represents one impersonated user account on the guest, so
+ every operation will use the same credentials specified when creating
+ the session object via <link to="IGuest::createSession"/>. Anonymous
+ sessions, that is, sessions without specifying a valid
+ user account on the guest are not allowed due to security reasons.
- <result name="VBOX_E_IPRT_ERROR">
- Error while looking up information.
- </result>
+ There can be a maximum of 32 sessions at once per VM. Each session keeps
+ track of its started guest processes, opened guest files or guest directories.
+ To work on guest files or directories a guest session offers methods to open
+ or create such objects (see <link to="IGuestSession::fileOpen"/> or
+ <link to="IGuestSession::directoryOpen"/> for example).
+
+ When done with either of these objects, including the guest session itself,
+ use the appropriate close() method to let the object do its cleanup work.
+
+ Every guest session has its own environment variable block which gets
+ automatically applied when starting a new guest process via
+ <link to="IGuestSession::processCreate"/> or <link to="IGuestSession::processCreateEx"/>.
+ To override (or unset) certain environment variables already set by the
+ guest session, one can specify a per-process environment block when using
+ one of the both above mentioned process creation calls.
+ Closing a session via <link to="IGuestSession::close" /> will try to close
+ all the mentioned objects above unless these objects are still used by
+ a client.
</desc>
- <param name="file" type="wstring" dir="in">
+ <param name="user" type="wstring" dir="in">
<desc>
- Full path of file to check.
- </desc>
- </param>
- <param name="userName" type="wstring" dir="in">
- <desc>
- User name under which the lookup will be performed; the
- user has to exist and have the appropriate rights to access / read the
- desired directory.
+ User name this session will be using to control the guest; has to exist
+ and have the appropriate rights to execute programs in the VM. Must not
+ be empty.
</desc>
</param>
<param name="password" type="wstring" dir="in">
<desc>
- Password of the user account specified.
- </desc>
- </param>
- <param name="exists" type="boolean" dir="return">
- <desc>
- True if it's a regular file, false if it isn't (or doesn't exist).
+ Password of the user account to be used. Empty passwords are allowed.
</desc>
</param>
- </method>
-
- <method name="fileQuerySize">
- <desc>
- Queries the size of a file, given the path to it.
-
- <result name="VBOX_E_IPRT_ERROR">
- Error while looking up information.
- </result>
-
- </desc>
- <param name="file" type="wstring" dir="in">
- <desc>
- Full path of file to query file size for.
- </desc>
- </param>
- <param name="userName" type="wstring" dir="in">
+ <param name="domain" type="wstring" dir="in">
<desc>
- User name under which the lookup will be performed; the
- user has to exist and have the appropriate rights to access / read the
- desired directory.
+ Domain name of the user account to be used if the guest is part of
+ a domain. Optional. This feature is not implemented yet.
</desc>
</param>
- <param name="password" type="wstring" dir="in">
+ <param name="sessionName" type="wstring" dir="in">
<desc>
- Password of the user account specified.
+ The session's friendly name. Optional, can be empty.
</desc>
</param>
- <param name="size" type="long long" dir="return">
+ <param name="guestSession" type="IGuestSession" dir="return">
<desc>
- Size (in bytes) of file specified.
+ The newly created session object.
</desc>
</param>
</method>
- <method name="setProcessInput">
+ <method name="findSession">
<desc>
- Sends input into a formerly started process.
-
- <result name="VBOX_E_IPRT_ERROR">
- Could not send input.
- </result>
-
+ Finds guest sessions by their friendly name and returns an interface
+ array with all found guest sessions.
</desc>
- <param name="pid" type="unsigned long" dir="in">
- <desc>
- Process id returned by earlier <link to="#executeProcess"/> call.
- </desc>
- </param>
- <param name="flags" type="unsigned long" dir="in">
+ <param name="sessionName" type="wstring" dir="in">
<desc>
- <link to="ProcessInputFlag"/> flags.
+ The session's friendly name to find. Wildcards like ? and * are allowed.
</desc>
</param>
- <param name="timeoutMS" type="unsigned long" dir="in">
+ <param name="sessions" type="IGuestSession" safearray="yes" dir="return">
<desc>
- The maximum timeout value (in msec) to wait for getting the
- data transfered to the guest. Pass 0 for an infinite timeout.
- </desc>
- </param>
- <param name="data" type="octet" dir="in" safearray="yes">
- <desc>
- Buffer of input data to send to the started process to.
- </desc>
- </param>
- <param name="written" type="unsigned long" dir="return">
- <desc>
- Number of bytes written.
+ Array with all guest sessions found matching the name specified.
</desc>
</param>
</method>
<method name="updateGuestAdditions">
<desc>
- Updates already installed Guest Additions in a VM
- (Windows guests only).
+ Automatically updates already installed Guest Additions in a VM.
+
+ At the moment only Windows guests are supported.
+
+ Because the VirtualBox Guest Additions drivers are not WHQL-certified
+ yet there might be warning dialogs during the actual Guest Additions
+ update. These need to be confirmed manually in order to continue the
+ installation process. This applies to Windows 2000 and Windows XP guests
+ and therefore these guests can't be updated in a fully automated fashion
+ without user interaction. However, to start a Guest Additions update for
+ the mentioned Windows versions anyway, the flag
+ AdditionsUpdateFlag_WaitForUpdateStartOnly can be specified. See
+ <link to="AdditionsUpdateFlag"/> for more information.
+
+ <result name="VBOX_E_NOT_SUPPORTED">
+ Guest OS is not supported for automated Guest Additions updates or the
+ already installed Guest Additions are not ready yet.
+ </result>
<result name="VBOX_E_IPRT_ERROR">
Error while updating.
@@ -9276,7 +11207,7 @@
Path to the Guest Additions .ISO file to use for the upate.
</desc>
</param>
- <param name="flags" type="unsigned long" dir="in">
+ <param name="flags" type="AdditionsUpdateFlag" dir="in" safearray="yes">
<desc>
<link to="AdditionsUpdateFlag"/> flags.
</desc>
@@ -9601,7 +11532,7 @@
to contain the disk data associated with the snapshot being deleted.
When deleting the current snapshot, the <link to="IMachine::currentSnapshot" />
- attribute is set to the current snapshot's parent or NULL if it
+ attribute is set to the current snapshot's parent or @c null if it
has no parent. Otherwise the attribute is unchanged.
</li>
</ul>
@@ -9806,7 +11737,7 @@
</const>
<const name="MultiAttach" value="5">
<desc>
- A medium which is is indirectly attached, so that one base medium can
+ A medium which is indirectly attached, so that one base medium can
be used for several VMs which have their own differencing medium to
store their modifications. In some sense a variant of Immutable
with unset AutoReset flag in each differencing medium.
@@ -9817,7 +11748,7 @@
<enum
name="MediumVariant"
- uuid="584ea502-143b-4ab0-ad14-d1028fdf0316"
+ uuid="80685b6b-e42f-497d-8271-e77bf3c61ada"
>
<desc>
Virtual medium image variant. More than one flag may be set.
@@ -9834,6 +11765,11 @@
VMDK image split in chunks of less than 2GByte.
</desc>
</const>
+ <const name="VmdkRawDisk" value="0x02">
+ <desc>
+ VMDK image representing a raw disk.
+ </desc>
+ </const>
<const name="VmdkStreamOptimized" value="0x04">
<desc>
VMDK streamOptimized image. Special import/export format which is
@@ -9865,7 +11801,7 @@
<interface
name="IMediumAttachment" extends="$unknown"
- uuid="b5dfbb8c-7498-48c3-bf10-78fc60f064e1"
+ uuid="5ee464d6-0613-4331-b154-7ce12170ef9f"
wsmap="struct"
>
<desc>
@@ -10091,6 +12027,10 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<desc>Whether the associated medium is non-rotational.</desc>
</attribute>
+ <attribute name="discard" type="boolean" readonly="yes">
+ <desc>Whether the associated medium supports discarding unused blocks.</desc>
+ </attribute>
+
<attribute name="bandwidthGroup" type="IBandwidthGroup" readonly="yes">
<desc>The bandwidth group this medium attachment is assigned to.</desc>
</attribute>
@@ -10099,7 +12039,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="IMedium" extends="$unknown"
- uuid="53f9cc0c-e0fd-40a5-a404-a7a5272082cd"
+ uuid="29989373-b111-4654-8493-2e1176cba890"
wsmap="managed"
>
<desc>
@@ -10153,7 +12093,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
When a medium has been opened or created using one of the aforementioned
APIs, it becomes "known" to VirtualBox. Known media can be attached
- to virtual machines and accessed through <link to="IVirtualBox::findMedium"/>.
+ to virtual machines and re-found through <link to="IVirtualBox::openMedium"/>.
They also appear in the global
<link to="IVirtualBox::hardDisks" />,
<link to="IVirtualBox::DVDImages" /> and
@@ -10578,7 +12518,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</desc>
</attribute>
- <method name="setIDs">
+ <method name="setIds">
<desc>
Changes the UUID and parent UUID for a hard disk medium.
</desc>
@@ -11238,6 +13178,52 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</param>
</method>
+ <method name="cloneToBase">
+ <desc>
+ Starts creating a clone of this medium in the format and at the
+ location defined by the @a target argument.
+
+ The target medium must be either in <link to="MediumState_NotCreated"/>
+ state (i.e. must not have an existing storage unit) or in
+ <link to="MediumState_Created"/> state (i.e. created and not locked, and
+ big enough to hold the data or else the copy will be partial). Upon
+ successful completion, the cloned medium will contain exactly the
+ same sector data as the medium being cloned, except that in the
+ first case a new UUID for the clone will be randomly generated, and in
+ the second case the UUID will remain unchanged.
+
+ The @a parent argument defines which medium will be the parent
+ of the clone. In this case the clone will be a base image, i.e.
+ completely independent. It is possible to specify an arbitrary
+ medium for this parameter, including the parent of the
+ medium which is being cloned. Even cloning to a child of the source
+ medium is possible. Note that when cloning to an existing image, the
+ @a parent argument is ignored.
+
+ After the returned progress object reports that the operation is
+ successfully complete, the target medium gets remembered by this
+ VirtualBox installation and may be attached to virtual machines.
+
+ <note>
+ This medium will be placed to <link to="MediumState_LockedRead"/>
+ state for the duration of this operation.
+ </note>
+ <result name="E_NOTIMPL">
+ The specified cloning variant is not supported at the moment.
+ </result>
+ </desc>
+ <param name="target" type="IMedium" dir="in">
+ <desc>Target medium.</desc>
+ </param>
+ <param name="variant" type="unsigned long" dir="in">
+ <desc>Exact image variant which should be created (as a combination of
+ <link to="MediumVariant" /> flags).</desc>
+ </param>
+ <param name="progress" type="IProgress" dir="return">
+ <desc>Progress object to track the operation completion.</desc>
+ </param>
+ </method>
+
<!-- other methods -->
<method name="compact">
@@ -12214,7 +14200,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="IDisplay" extends="$unknown"
- uuid="09EED313-CD56-4D06-BD56-FAC0F716B5DD"
+ uuid="b83ee395-8679-40ca-8d60-1a0cbe724930"
wsmap="managed"
>
<desc>
@@ -12278,10 +14264,36 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</result>
</desc>
+ <param name="display" type="unsigned long" dir="in">
+ <desc>
+ The number of the guest display to send the hint to.
+ </desc>
+ </param>
+ <param name="enabled" type="boolean" dir="in">
+ <desc>
+ @c True, if this guest screen is enabled,
+ @c False otherwise.
+ </desc>
+ </param>
+ <param name="changeOrigin" type="boolean" dir="in">
+ <desc>
+ @c True, if the origin of the guest screen should be changed,
+ @c False otherwise.
+ </desc>
+ </param>
+ <param name="originX" type="long" dir="in">
+ <desc>
+ The X origin of the guest screen.
+ </desc>
+ </param>
+ <param name="originY" type="long" dir="in">
+ <desc>
+ The Y origin of the guest screen.
+ </desc>
+ </param>
<param name="width" type="unsigned long" dir="in"/>
<param name="height" type="unsigned long" dir="in"/>
<param name="bitsPerPixel" type="unsigned long" dir="in"/>
- <param name="display" type="unsigned long" dir="in"/>
</method>
<method name="setSeamlessMode">
@@ -12476,6 +14488,42 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</param>
</method>
+ <method name="viewportChanged">
+ <desc>
+ Signals that framebuffer window viewport has changed.
+
+ <result name="E_INVALIDARG">
+ The specified viewport data is invalid.
+ </result>
+
+ </desc>
+
+ <param name="screenId" type="unsigned long" dir="in">
+ <desc>
+ Monitor to take the screenshot from.
+ </desc>
+ </param>
+ <param name="x" type="unsigned long" dir="in">
+ <desc>
+ Framebuffer x offset.
+ </desc>
+ </param>
+ <param name="y" type="unsigned long" dir="in">
+ <desc>
+ Framebuffer y offset.
+ </desc>
+ </param>
+ <param name="width" type="unsigned long" dir="in">
+ <desc>
+ Viewport width.
+ </desc>
+ </param>
+ <param name="height" type="unsigned long" dir="in">
+ <desc>
+ Viewport height.
+ </desc>
+ </param>
+ </method>
</interface>
<!--
@@ -12559,7 +14607,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="INetworkAdapter" extends="$unknown"
- uuid="8b2e705c-0547-4008-b7bc-788757346092"
+ uuid="efa0f965-63c7-4c60-afdf-b1cc9943b9c0"
wsmap="managed"
>
<desc>
@@ -12676,7 +14724,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</desc>
</attribute>
- <attribute name="natDriver" type="INATEngine" readonly="yes">
+ <attribute name="NATEngine" type="INATEngine" readonly="yes">
<desc>
Points to the NAT engine which handles the network address translation
for this interface. This is active only when the interface actually uses
@@ -12941,7 +14989,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="IMachineDebugger" extends="$unknown"
- uuid="1bfd2fa9-0d91-44d3-9515-368dcbb3eb4d"
+ uuid="a9abbb7c-d678-43b2-bed2-19ec0e32303d"
wsmap="suppress"
>
<method name="dumpGuestCore">
@@ -13273,8 +15321,8 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</param>
</method>
- <attribute name="singlestep" type="boolean">
- <desc>Switch for enabling singlestepping.</desc>
+ <attribute name="singleStep" type="boolean">
+ <desc>Switch for enabling single-stepping.</desc>
</attribute>
<attribute name="recompileUser" type="boolean">
@@ -13297,18 +15345,30 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<desc>Switch for enabling and disabling the debug logger.</desc>
</attribute>
- <attribute name="logFlags" type="wstring" readonly="yes">
+ <attribute name="logDbgFlags" type="wstring" readonly="yes">
<desc>The debug logger flags.</desc>
</attribute>
- <attribute name="logGroups" type="wstring" readonly="yes">
+ <attribute name="logDbgGroups" type="wstring" readonly="yes">
<desc>The debug logger's group settings.</desc>
</attribute>
- <attribute name="logDestinations" type="wstring" readonly="yes">
+ <attribute name="logDbgDestinations" type="wstring" readonly="yes">
<desc>The debug logger's destination settings.</desc>
</attribute>
+ <attribute name="logRelFlags" type="wstring" readonly="yes">
+ <desc>The release logger flags.</desc>
+ </attribute>
+
+ <attribute name="logRelGroups" type="wstring" readonly="yes">
+ <desc>The release logger's group settings.</desc>
+ </attribute>
+
+ <attribute name="logRelDestinations" type="wstring" readonly="yes">
+ <desc>The relase logger's destination settings.</desc>
+ </attribute>
+
<attribute name="HWVirtExEnabled" type="boolean" readonly="yes">
<desc>
Flag indicating whether the VM is currently making use of CPU hardware
@@ -13378,7 +15438,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="IUSBController" extends="$unknown"
- uuid="6fdcccc5-abd3-4fec-9387-2ad3914fc4a8"
+ uuid="01e6f13a-0580-452f-a40f-74e32a5e4921"
wsmap="managed"
>
<attribute name="enabled" type="boolean">
@@ -13390,7 +15450,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</desc>
</attribute>
- <attribute name="enabledEhci" type="boolean">
+ <attribute name="enabledEHCI" type="boolean">
<desc>
Flag whether the USB EHCI controller is present in the
guest system. If disabled, the virtual guest hardware will
@@ -14259,7 +16319,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="IInternalSessionControl" extends="$unknown"
- uuid="c2b4cd5f-d3ce-4dd6-b915-123272163ef5"
+ uuid="3e83963a-1c3b-400d-8c5f-f2d077b0a597"
internal="yes"
wsmap="suppress"
>
@@ -14299,6 +16359,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</desc>
<param name="machine" type="IMachine" dir="in"/>
+ <param name="lockType" type="LockType" dir="in"/>
</method>
<method name="assignRemoteMachine">
@@ -14453,6 +16514,24 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</param>
</method>
+ <method name="onClipboardModeChange">
+ <desc>
+ Notification when the shared clipboard mode changes.
+ </desc>
+ <param name="clipboardMode" type="ClipboardMode" dir="in">
+ <desc>The new shared clipboard mode.</desc>
+ </param>
+ </method>
+
+ <method name="onDragAndDropModeChange">
+ <desc>
+ Notification when the drag'n'drop mode changes.
+ </desc>
+ <param name="dragAndDropMode" type="DragAndDropMode" dir="in">
+ <desc>The new mode for drag'n'drop.</desc>
+ </param>
+ </method>
+
<method name="onCPUChange">
<desc>
Notification when a CPU changes.
@@ -15029,42 +17108,6 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
Returns whether it is possible to boot from disks attached to this controller.
</desc>
</attribute>
-
- <method name="getIDEEmulationPort">
- <desc>
- Gets the corresponding port number which is emulated as an IDE device.
- Works only with SATA controllers.
-
- <result name="E_INVALIDARG">
- The @a devicePosition is not in the range 0 to 3.
- </result>
- <result name="E_NOTIMPL">
- The storage controller type is not SATAIntelAhci.
- </result>
-
- </desc>
- <param name="devicePosition" type="long" dir="in"/>
- <param name="portNumber" type="long" dir="return"/>
- </method>
-
- <method name="setIDEEmulationPort">
- <desc>
- Sets the port number which is emulated as an IDE device.
- Works only with SATA controllers.
-
- <result name="E_INVALIDARG">
- The @a devicePosition is not in the range 0 to 3 or the
- @a portNumber is not in the range 0 to 29.
- </result>
- <result name="E_NOTIMPL">
- The storage controller type is not SATAIntelAhci.
- </result>
-
- </desc>
- <param name="devicePosition" type="long" dir="in"/>
- <param name="portNumber" type="long" dir="in"/>
- </method>
-
</interface>
<if target="wsdl">
@@ -15160,7 +17203,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<method name="logoff">
<desc>
- Logs off the client who has previously logged on with <link to="IWebsessionManager::logoff" />
+ Logs off the client who has previously logged on with <link to="IWebsessionManager::logon" />
and destroys all resources associated with the session (most importantly, all
managed objects created in the server while the session was active).
</desc>
@@ -15619,12 +17662,12 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="INATEngine" extends="$unknown"
- uuid="4b286616-eb03-11de-b0fb-1701eca42246"
+ uuid="26451b99-3b2d-4dcb-8e4b-d63654218175"
wsmap="managed"
>
<desc>Interface for managing a NAT engine which is used with a virtual machine. This
allows for changing NAT behavior such as port-forwarding rules. This interface is
- used in the <link to="INetworkAdapter::natDriver" /> attribute.</desc>
+ used in the <link to="INetworkAdapter::NATEngine" /> attribute.</desc>
<attribute name="network" type="wstring">
<desc>The network attribute of the NAT engine (the same value is used with built-in
DHCP server to fill corresponding fields of DHCP leases).</desc>
@@ -15634,15 +17677,15 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<note>Changing this does not change binding of port forwarding.</note>
</desc>
</attribute>
- <attribute name="tftpPrefix" type="wstring">
+ <attribute name="TFTPPrefix" type="wstring">
<desc>TFTP prefix attribute which is used with the built-in DHCP server to fill
the corresponding fields of DHCP leases.</desc>
</attribute>
- <attribute name="tftpBootFile" type="wstring">
+ <attribute name="TFTPBootFile" type="wstring">
<desc>TFTP boot file attribute which is used with the built-in DHCP server to fill
the corresponding fields of DHCP leases.</desc>
</attribute>
- <attribute name="tftpNextServer" type="wstring">
+ <attribute name="TFTPNextServer" type="wstring">
<desc>TFTP server attribute which is used with the built-in DHCP server to fill
the corresponding fields of DHCP leases.
<note>The preferred form is IPv4 addresses.</note>
@@ -15651,14 +17694,14 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<attribute name="aliasMode" type="unsigned long">
<desc></desc>
</attribute>
- <attribute name="dnsPassDomain" type="boolean">
+ <attribute name="DNSPassDomain" type="boolean">
<desc>Whether the DHCP server should pass the DNS domain used by the host.</desc>
</attribute>
- <attribute name="dnsProxy" type="boolean">
+ <attribute name="DNSProxy" type="boolean">
<desc>Whether the DHCP server (and the DNS traffic by NAT) should pass the address
of the DNS proxy and process traffic using DNS servers registered on the host.</desc>
</attribute>
- <attribute name="dnsUseHostResolver" type="boolean">
+ <attribute name="DNSUseHostResolver" type="boolean">
<desc>Whether the DHCP server (and the DNS traffic by NAT) should pass the address
of the DNS proxy and process traffic using the host resolver mechanism.</desc>
</attribute>
@@ -15704,14 +17747,14 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<param name="proto" type="NATProtocol" dir="in">
<desc>Protocol handled with the rule.</desc>
</param>
- <param name="hostIp" type="wstring" dir="in">
+ <param name="hostIP" type="wstring" dir="in">
<desc>IP of the host interface to which the rule should apply. An empty ip address is
acceptable, in which case the NAT engine binds the handling socket to any interface.</desc>
</param>
<param name="hostPort" type="unsigned short" dir="in">
<desc>The port number to listen on.</desc>
</param>
- <param name="guestIp" type="wstring" dir="in">
+ <param name="guestIP" type="wstring" dir="in">
<desc>The IP address of the guest which the NAT engine will forward matching packets
to. An empty IP address is acceptable, in which case the NAT engine will forward
packets to the first DHCP lease (x.x.x.15).</desc>
@@ -15760,7 +17803,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="IExtPackBase" extends="$unknown"
- uuid="5ffb0b64-0ad6-467d-af62-1157e7dc3c99"
+ uuid="f79b75d8-2890-4f34-ffff-ffffa144e82c"
wsmap="suppress"
>
<desc>
@@ -15775,15 +17818,27 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</attribute>
<attribute name="version" type="wstring" readonly="yes">
<desc>
- The extension pack version string. This is on the same form as
- other VirtualBox version strings, i.e.: "1.2.3", "1.2.3_BETA1",
- "1.2.3-OSE", "1.2.3r45678", "1.2.3r45678-OSE", "1.2.3_BETA1-r45678"
- or "1.2.3_BETA1-r45678-OSE"
+ The extension pack version string. This is restricted to the dotted
+ version number and optionally a build indicator. No tree revision or
+ tag will be included in the string as those things are available as
+ separate properties. An optional publisher tag may be present like for
+ <link to="IVirtualBox::version"/>.
+
+ Examples: "1.2.3", "1.2.3_BETA1" and "1.2.3_RC2".
</desc>
</attribute>
<attribute name="revision" type="unsigned long" readonly="yes">
<desc>The extension pack internal revision number.</desc>
</attribute>
+ <attribute name="edition" type="wstring" readonly="yes">
+ <desc>
+ Edition indicator. This is usually empty.
+
+ Can for instance be used to help distinguishing between two editions
+ of the same extension pack where only the license, service contract or
+ something differs.
+ </desc>
+ </attribute>
<attribute name="VRDEModule" type="wstring" readonly="yes">
<desc>The name of the VRDE module if the extension pack sports one.</desc>
</attribute>
@@ -16067,8 +18122,8 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<desc>How many devices/medium attachements use this group.</desc>
</attribute>
- <attribute name="maxMbPerSec" type="unsigned long">
- <desc>The maximum number of MBytes which can be transfered by all
+ <attribute name="maxBytesPerSec" type="long long">
+ <desc>The maximum number of bytes which can be transfered by all
entities attached to this group during one second.</desc>
</attribute>
@@ -16105,8 +18160,8 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<param name="type" type="BandwidthGroupType" dir="in">
<desc>The type of the bandwidth group (network or disk).</desc>
</param>
- <param name="maxMbPerSec" type="unsigned long" dir="in">
- <desc>The maximum number of MBytes which can be transfered by all
+ <param name="maxBytesPerSec" type="long long" dir="in">
+ <desc>The maximum number of bytes which can be transfered by all
entities attached to this group during one second.</desc>
</param>
</method>
@@ -16190,7 +18245,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
-->
<enum
name="VBoxEventType"
- uuid="cce48db6-8561-479d-8d46-1358bab45d4e"
+ uuid="0d67e79e-b7b1-4919-aab3-b36866075515"
>
<desc>
@@ -16423,9 +18478,9 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
See <link to="INATRedirectEvent">INATRedirectEvent</link>.
</desc>
</const>
- <const name="OnHostPciDevicePlug" value="67">
+ <const name="OnHostPCIDevicePlug" value="67">
<desc>
- See <link to="IHostPciDevicePlugEvent">IHostPciDevicePlugEvent</link>.
+ See <link to="IHostPCIDevicePlugEvent">IHostPCIDevicePlugEvent</link>.
</desc>
</const>
<const name="OnVBoxSVCAvailabilityChanged" value="68">
@@ -16448,9 +18503,19 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
See <link to="IStorageDeviceChangedEvent">IStorageDeviceChangedEvent</link>.
</desc>
</const>
+ <const name="OnClipboardModeChanged" value="72">
+ <desc>
+ See <link to="IClipboardModeChangedEvent">IClipboardModeChangedEvent</link>.
+ </desc>
+ </const>
+ <const name="OnDragAndDropModeChanged" value="73">
+ <desc>
+ See <link to="IDragAndDropModeChangedEvent">IDragAndDropModeChangedEvent</link>.
+ </desc>
+ </const>
<!-- Last event marker -->
- <const name="Last" value="72">
+ <const name="Last" value="74">
<desc>
Must be last event, used for iterations and structures relying on numerical event values.
</desc>
@@ -17196,14 +19261,44 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</interface>
<interface
+ name="IClipboardModeChangedEvent" extends="IEvent"
+ uuid="cac21692-7997-4595-a731-3a509db604e5"
+ wsmap="managed" autogen="VBoxEvent" id="OnClipboardModeChanged"
+ >
+ <desc>
+ Notification when the shared clipboard mode changes.
+ </desc>
+ <attribute name="clipboardMode" type="ClipboardMode" readonly="yes">
+ <desc>
+ The new clipboard mode.
+ </desc>
+ </attribute>
+ </interface>
+
+ <interface
+ name="IDragAndDropModeChangedEvent" extends="IEvent"
+ uuid="e90b8850-ac8e-4dff-8059-4100ae2c3c3d"
+ wsmap="managed" autogen="VBoxEvent" id="OnDragAndDropModeChanged"
+ >
+ <desc>
+ Notification when the drag'n'drop mode changes.
+ </desc>
+ <attribute name="dragAndDropMode" type="DragAndDropMode" readonly="yes">
+ <desc>
+ The new drag'n'drop mode.
+ </desc>
+ </attribute>
+ </interface>
+
+ <interface
name="ICPUChangedEvent" extends="IEvent"
- uuid="D0F0BECC-EE17-4D17-A8CC-383B0EB55E9D"
+ uuid="4da2dec7-71b2-4817-9a64-4ed12c17388e"
wsmap="managed" autogen="VBoxEvent" id="OnCPUChanged"
>
<desc>
Notification when a CPU changes.
</desc>
- <attribute name="cpu" type="unsigned long" readonly="yes">
+ <attribute name="CPU" type="unsigned long" readonly="yes">
<desc>
The CPU which changed.
</desc>
@@ -17654,7 +19749,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
<interface
name="INATRedirectEvent" extends="IMachineEvent"
- uuid="57DE97D7-3CBB-42A0-888F-610D5832D16B"
+ uuid="24eef068-c380-4510-bc7c-19314a7352f1"
wsmap="managed" autogen="VBoxEvent" id="OnNATRedirect"
>
<desc>
@@ -17680,7 +19775,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
Protocol (TCP or UDP) of the redirect rule.
</desc>
</attribute>
- <attribute name="hostIp" type="wstring" readonly="yes">
+ <attribute name="hostIP" type="wstring" readonly="yes">
<desc>
Host ip address to bind socket on.
</desc>
@@ -17690,7 +19785,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
Host port to bind socket on.
</desc>
</attribute>
- <attribute name="guestIp" type="wstring" readonly="yes">
+ <attribute name="guestIP" type="wstring" readonly="yes">
<desc>
Guest ip address to redirect to.
</desc>
@@ -17703,17 +19798,17 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</interface>
<interface
- name="IHostPciDevicePlugEvent" extends="IMachineEvent"
+ name="IHostPCIDevicePlugEvent" extends="IMachineEvent"
waitable="yes"
- uuid="9cebfc27-c579-4965-8eb7-d31794cd7dcf"
- wsmap="managed" autogen="VBoxEvent" id="OnHostPciDevicePlug"
+ uuid="a0bad6df-d612-47d3-89d4-db3992533948"
+ wsmap="managed" autogen="VBoxEvent" id="OnHostPCIDevicePlug"
>
<desc>
Notification when host PCI device is plugged/unplugged. Plugging
usually takes place on VM startup, unplug - when
- <link to="IMachine::detachHostPciDevice"/> is called.
+ <link to="IMachine::detachHostPCIDevice"/> is called.
- <see><link to="IMachine::detachHostPciDevice"/></see>
+ <see><link to="IMachine::detachHostPCIDevice"/></see>
</desc>
@@ -17730,7 +19825,7 @@ Snapshot 1 (B.vdi) Snapshot 1 (B.vdi)
</desc>
</attribute>
- <attribute name="attachment" type="IPciDeviceAttachment" readonly="yes">
+ <attribute name="attachment" type="IPCIDeviceAttachment" readonly="yes">
<desc>
Attachment info for this device.
</desc>
diff --git a/src/VBox/Main/idl/comimpl.xsl b/src/VBox/Main/idl/comimpl.xsl
index e92386190..58889cbdb 100644
--- a/src/VBox/Main/idl/comimpl.xsl
+++ b/src/VBox/Main/idl/comimpl.xsl
@@ -13,15 +13,15 @@
rather trivial container classes for their read-only attributes.
Further extension to other interfaces is possible and anticipated.
- Copyright (C) 2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2010-2012 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:output
@@ -37,24 +37,24 @@
<xsl:template name="fileheader">
<xsl:param name="name" />
- <xsl:text>/**
- * Copyright (C) 2010 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
-</xsl:text>
- <xsl:value-of select="concat(' * ',$name)"/>
-<xsl:text>
- *
+ <xsl:text>/** @file </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>
* DO NOT EDIT! This is a generated file.
* Generated from: src/VBox/Main/idl/VirtualBox.xidl (VirtualBox's interface definitions in XML)
- * Generator: src/VBox/Main/idl/autogen.xsl
+ * Generator: src/VBox/Main/idl/comimpl.xsl
+ */
+
+/*
+ * Copyright (C) 2010-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
</xsl:text>
@@ -742,7 +742,7 @@ HRESULT VBoxEventDesc::reinit(VBoxEventType_T aType, ...)
<xsl:variable name="extends">
<xsl:value-of select="//interface[@name=$name]/@extends" />
</xsl:variable>
-
+
<xsl:choose>
<xsl:when test="$extends='IEvent'">
</xsl:when>
@@ -770,7 +770,7 @@ HRESULT VBoxEventDesc::reinit(VBoxEventType_T aType, ...)
<xsl:with-param name="dir" select="'in'" />
<xsl:with-param name="mod" select="@mod" />
</xsl:call-template>
- </xsl:variable>
+ </xsl:variable>
<xsl:value-of select="concat(', ',$aTypeName)"/>
</xsl:for-each>
</xsl:template>
@@ -840,13 +840,13 @@ HRESULT VBoxEventDesc::reinit(VBoxEventType_T aType, ...)
</xsl:call-template>
<xsl:value-of select=" ')&#10;{&#10;'"/>
- <xsl:value-of select=" ' VBoxEventDesc evDesc;&#10;'"/>
- <xsl:value-of select="concat(' evDesc.init(aSource, VBoxEventType_',$evid)"/>
+ <xsl:value-of select=" ' VBoxEventDesc evDesc;&#10;'"/>
+ <xsl:value-of select="concat(' evDesc.init(aSource, VBoxEventType_',$evid)"/>
<xsl:call-template name="genFactParams">
<xsl:with-param name="name" select="$ifname" />
</xsl:call-template>
<xsl:value-of select="');&#10;'"/>
- <xsl:value-of select=" ' evDesc.fire(/* do not wait for delivery */ 0);&#10;'"/>
+ <xsl:value-of select=" ' evDesc.fire(/* do not wait for delivery */ 0);&#10;'"/>
<xsl:value-of select=" '}&#10;'"/>
</xsl:for-each>
</xsl:template>
diff --git a/src/VBox/Main/idl/docstrip.xsl b/src/VBox/Main/idl/docstrip.xsl
index 2ff1e07f6..0cbdac4a5 100644
--- a/src/VBox/Main/idl/docstrip.xsl
+++ b/src/VBox/Main/idl/docstrip.xsl
@@ -9,15 +9,15 @@
original XIDL should not cause a full recompile of nearly all of
VirtualBox.
- Copyright (C) 2009-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2009-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
diff --git a/src/VBox/Main/idl/doxygen.xsl b/src/VBox/Main/idl/doxygen.xsl
index 78b81b69f..bc55d3d91 100644
--- a/src/VBox/Main/idl/doxygen.xsl
+++ b/src/VBox/Main/idl/doxygen.xsl
@@ -5,15 +5,15 @@
* definition expressed in XML. The generated file is intended solely to
* generate the documentation using Doxygen.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
diff --git a/src/VBox/Main/idl/midl.xsl b/src/VBox/Main/idl/midl.xsl
index c2fd56bc0..0ded778f4 100644
--- a/src/VBox/Main/idl/midl.xsl
+++ b/src/VBox/Main/idl/midl.xsl
@@ -5,15 +5,15 @@
* A template to generate a MS IDL compatible interface definition file
* from the generic interface definition expressed in XML.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2012 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
@@ -287,18 +287,13 @@
<xsl:call-template name="capitalize">
<xsl:with-param name="str" select="@name"/>
</xsl:call-template>
- <xsl:text> ([in</xsl:text>
- <xsl:if test="@safearray='yes'">
- <!-- VB supports only [in, out], [out] and [out, retval] arrays -->
- <xsl:text>, out</xsl:text>
- </xsl:if>
- <xsl:text>] </xsl:text>
+ <xsl:text> ([in] </xsl:text>
<xsl:if test="@safearray='yes'">
<xsl:text>SAFEARRAY(</xsl:text>
</xsl:if>
<xsl:apply-templates select="@type"/>
<xsl:if test="@safearray='yes'">
- <xsl:text>) *</xsl:text>
+ <xsl:text>)</xsl:text>
</xsl:if>
<xsl:text> a</xsl:text>
<xsl:call-template name="capitalize">
diff --git a/src/VBox/Main/idl/xpidl.xsl b/src/VBox/Main/idl/xpidl.xsl
index e53819da7..18796ba63 100644
--- a/src/VBox/Main/idl/xpidl.xsl
+++ b/src/VBox/Main/idl/xpidl.xsl
@@ -5,15 +5,15 @@
* A template to generate a XPCOM IDL compatible interface definition file
* from the generic interface definition expressed in XML.
- Copyright (C) 2006-2009 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2009 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
diff --git a/src/VBox/Main/include/AdditionsFacilityImpl.h b/src/VBox/Main/include/AdditionsFacilityImpl.h
index 46193a997..1d624f628 100644
--- a/src/VBox/Main/include/AdditionsFacilityImpl.h
+++ b/src/VBox/Main/include/AdditionsFacilityImpl.h
@@ -1,5 +1,4 @@
/** @file
- *
* VirtualBox COM class implementation
*/
diff --git a/src/VBox/Main/include/ApplianceImpl.h b/src/VBox/Main/include/ApplianceImpl.h
index d6f22a5ec..16c96893b 100644
--- a/src/VBox/Main/include/ApplianceImpl.h
+++ b/src/VBox/Main/include/ApplianceImpl.h
@@ -34,7 +34,7 @@ struct VirtualSystemDescriptionEntry;
struct LocationInfo;
typedef struct VDINTERFACE *PVDINTERFACE;
typedef struct VDINTERFACEIO *PVDINTERFACEIO;
-typedef struct SHA1STORAGE *PSHA1STORAGE;
+typedef struct SHASTORAGE *PSHASTORAGE;
namespace ovf
{
@@ -76,7 +76,8 @@ public:
{
unspecified,
OVF_0_9,
- OVF_1_0
+ OVF_1_0,
+ OVF_2_0
};
// public initializer/uninitializer for internal purposes only
@@ -149,7 +150,7 @@ private:
HRESULT readFS(TaskOVF *pTask);
HRESULT readFSOVF(TaskOVF *pTask);
HRESULT readFSOVA(TaskOVF *pTask);
- HRESULT readFSImpl(TaskOVF *pTask, const RTCString &strFilename, PVDINTERFACEIO pCallbacks, PSHA1STORAGE pStorage);
+ HRESULT readFSImpl(TaskOVF *pTask, const RTCString &strFilename, PVDINTERFACEIO pCallbacks, PSHASTORAGE pStorage);
HRESULT readS3(TaskOVF *pTask);
/*******************************************************************************
@@ -163,8 +164,8 @@ private:
HRESULT importFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock);
HRESULT importS3(TaskOVF *pTask);
- HRESULT readManifestFile(const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHA1STORAGE pStorage);
- HRESULT readTarManifestFile(RTTAR tar, const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHA1STORAGE pStorage);
+ HRESULT readManifestFile(const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHASTORAGE pStorage);
+ HRESULT readTarManifestFile(RTTAR tar, const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHASTORAGE pStorage);
HRESULT verifyManifestFile(const Utf8Str &strFile, ImportStack &stack, void *pvBuf, size_t cbSize);
void convertDiskAttachmentValues(const ovf::HardDiskController &hdc,
@@ -178,21 +179,21 @@ private:
ComObjPtr<Medium> &pTargetHD,
ImportStack &stack,
PVDINTERFACEIO pCallbacks,
- PSHA1STORAGE pStorage);
+ PSHASTORAGE pStorage);
void importMachineGeneric(const ovf::VirtualSystem &vsysThis,
ComObjPtr<VirtualSystemDescription> &vsdescThis,
ComPtr<IMachine> &pNewMachine,
ImportStack &stack,
PVDINTERFACEIO pCallbacks,
- PSHA1STORAGE pStorage);
+ PSHASTORAGE pStorage);
void importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThis,
ComPtr<IMachine> &pNewMachine,
ImportStack &stack,
PVDINTERFACEIO pCallbacks,
- PSHA1STORAGE pStorage);
+ PSHASTORAGE pStorage);
void importMachines(ImportStack &stack,
PVDINTERFACEIO pCallbacks,
- PSHA1STORAGE pStorage);
+ PSHASTORAGE pStorage);
/*******************************************************************************
* Write stuff
@@ -203,7 +204,7 @@ private:
HRESULT writeFS(TaskOVF *pTask);
HRESULT writeFSOVF(TaskOVF *pTask, AutoWriteLockBase& writeLock);
HRESULT writeFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock);
- HRESULT writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVDINTERFACEIO pCallbacks, PSHA1STORAGE pStorage);
+ HRESULT writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVDINTERFACEIO pCallbacks, PSHASTORAGE pStorage);
HRESULT writeS3(TaskOVF *pTask);
struct XMLStack;
diff --git a/src/VBox/Main/include/ApplianceImplPrivate.h b/src/VBox/Main/include/ApplianceImplPrivate.h
index e67033583..ee2f39d8a 100644
--- a/src/VBox/Main/include/ApplianceImplPrivate.h
+++ b/src/VBox/Main/include/ApplianceImplPrivate.h
@@ -51,6 +51,7 @@ struct Appliance::Data
Data()
: state(ApplianceIdle)
, fManifest(true)
+ , fSha256(false)
, pReader(NULL)
, ulWeightForXmlOperation(0)
, ulWeightForManifestOperation(0)
@@ -72,6 +73,7 @@ struct Appliance::Data
LocationInfo locInfo; // location info for the currently processed OVF
bool fManifest; // Create a manifest file on export
+ bool fSha256; // true = SHA256 (OVF 2.0), false = SHA1 (OVF 1.0)
RTCList<ImportOptions_T> optList;
ovf::OVFReader *pReader;
@@ -85,7 +87,7 @@ struct Appliance::Data
ULONG ulWeightForManifestOperation;
ULONG ulTotalDisksMB;
ULONG cDisks;
- Utf8Str strOVFSHA1Digest;
+ Utf8Str strOVFSHADigest;
std::list<Guid> llGuidsMachinesCreated;
};
@@ -223,18 +225,19 @@ ovf::CIMOSType_T convertVBoxOSType2CIMOSType(const char *pcszVbox);
Utf8Str convertNetworkAttachmentTypeToString(NetworkAttachmentType_T type);
-typedef struct SHA1STORAGE
+typedef struct SHASTORAGE
{
PVDINTERFACE pVDImageIfaces;
bool fCreateDigest;
+ bool fSha256; /* false = SHA1 (OVF 1.x), true = SHA256 (OVF 2.0) */
Utf8Str strDigest;
-} SHA1STORAGE, *PSHA1STORAGE;
+} SHASTORAGE, *PSHASTORAGE;
-PVDINTERFACEIO Sha1CreateInterface();
+PVDINTERFACEIO ShaCreateInterface();
PVDINTERFACEIO FileCreateInterface();
PVDINTERFACEIO TarCreateInterface();
-int Sha1ReadBuf(const char *pcszFilename, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, void *pvUser);
-int Sha1WriteBuf(const char *pcszFilename, void *pvBuf, size_t cbSize, PVDINTERFACEIO pCallbacks, void *pvUser);
+int ShaReadBuf(const char *pcszFilename, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pIfIo, void *pvUser);
+int ShaWriteBuf(const char *pcszFilename, void *pvBuf, size_t cbSize, PVDINTERFACEIO pIfIo, void *pvUser);
#endif // ____H_APPLIANCEIMPLPRIVATE
diff --git a/src/VBox/Main/include/AutoCaller.h b/src/VBox/Main/include/AutoCaller.h
index 42bd5af71..207d35891 100644
--- a/src/VBox/Main/include/AutoCaller.h
+++ b/src/VBox/Main/include/AutoCaller.h
@@ -173,8 +173,13 @@ private:
* STDMETHODIMP Component::Foo()
* {
* AutoCaller autoCaller(this);
- * if (FAILED(autoCaller.rc())) return autoCaller.rc();
- * ...
+ * HRESULT hrc = autoCaller.rc();
+ * if (SUCCEEDED(hrc))
+ * {
+ * ...
+ * }
+ * return hrc;
+ * }
* </code>
*
* Using this class is equivalent to using the AutoCallerBase template with
@@ -198,8 +203,12 @@ typedef AutoCallerBase<false> AutoCaller;
* STDMETHODIMP Component::Bar()
* {
* AutoLimitedCaller autoCaller(this);
- * if (FAILED(autoCaller.rc())) return autoCaller.rc();
- * ...
+ * HRESULT hrc = autoCaller.rc();
+ * if (SUCCEEDED(hrc))
+ * {
+ * ...
+ * }
+ * return hrc;
* </code>
*
* Using this class is equivalent to using the AutoCallerBase template with
@@ -243,8 +252,8 @@ typedef AutoCallerBase<true> AutoLimitedCaller;
* <code>
* HRESULT Component::init()
* {
- * AutoInitSpan autoInitSpan (this);
- * AssertReturn (autoInitSpan.isOk(), E_FAIL);
+ * AutoInitSpan autoInitSpan(this);
+ * AssertReturn(autoInitSpan.isOk(), E_FAIL);
* ...
* if (FAILED(rc))
* return rc;
diff --git a/src/VBox/Main/include/AutostartDb.h b/src/VBox/Main/include/AutostartDb.h
new file mode 100644
index 000000000..541766eb3
--- /dev/null
+++ b/src/VBox/Main/include/AutostartDb.h
@@ -0,0 +1,95 @@
+/** @file
+ * Main - Autostart database Interfaces.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___autostart_h
+#define ___autostart_h
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/critsect.h>
+
+class AutostartDb
+{
+ public:
+
+ AutostartDb();
+ ~AutostartDb();
+
+ /**
+ * Sets the path to the autostart database.
+ *
+ * @returns VBox status code.
+ * @param pszAutostartDbPathNew Path to the autostart database.
+ */
+ int setAutostartDbPath(const char *pszAutostartDbPathNew);
+
+ /**
+ * Add a autostart VM to the global database.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PATH_NOT_FOUND if the autostart database directory is not set.
+ * @param pszVMId ID of the VM to add.
+ */
+ int addAutostartVM(const char *pszVMId);
+
+ /**
+ * Remove a autostart VM from the global database.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PATH_NOT_FOUND if the autostart database directory is not set.
+ * @param pszVMId ID of the VM to remove.
+ */
+ int removeAutostartVM(const char *pszVMId);
+
+ /**
+ * Add a autostop VM to the global database.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PATH_NOT_FOUND if the autostart database directory is not set.
+ * @param pszVMId ID of the VM to add.
+ */
+ int addAutostopVM(const char *pszVMId);
+
+ /**
+ * Remove a autostop VM from the global database.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PATH_NOT_FOUND if the autostart database directory is not set.
+ * @param pszVMId ID of the VM to remove.
+ */
+ int removeAutostopVM(const char *pszVMId);
+
+ private:
+
+#ifdef RT_OS_LINUX
+ /** Critical section protecting the database against concurrent access. */
+ RTCRITSECT CritSect;
+ /** Path to the autostart database. */
+ char *m_pszAutostartDbPath;
+
+ /**
+ * Autostart database modification worker.
+ *
+ * @returns VBox status code.
+ * @param fAutostart Flag whether the autostart or autostop database is modified.
+ * @param fAddVM Flag whether a VM is added or removed from the database.
+ */
+ int autostartModifyDb(bool fAutostart, bool fAddVM);
+#endif
+};
+
+#endif /* !___autostart_h */
+
diff --git a/src/VBox/Main/include/BandwidthControlImpl.h b/src/VBox/Main/include/BandwidthControlImpl.h
index 98101cc5d..f6a4b7032 100644
--- a/src/VBox/Main/include/BandwidthControlImpl.h
+++ b/src/VBox/Main/include/BandwidthControlImpl.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2009 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -24,7 +24,7 @@ class BandwidthGroup;
namespace settings
{
- struct IoSettings;
+ struct IOSettings;
}
class ATL_NO_VTABLE BandwidthControl :
@@ -51,7 +51,7 @@ public:
HRESULT initCopy(Machine *aParent, BandwidthControl *aThat);
void uninit();
- STDMETHOD(CreateBandwidthGroup) (IN_BSTR aName, BandwidthGroupType_T aType, ULONG aMaxMbPerSec);
+ STDMETHOD(CreateBandwidthGroup) (IN_BSTR aName, BandwidthGroupType_T aType, LONG64 aMaxBytesPerSec);
STDMETHOD(DeleteBandwidthGroup) (IN_BSTR aName);
STDMETHOD(COMGETTER(NumGroups)) (ULONG *aGroups);
STDMETHOD(GetBandwidthGroup) (IN_BSTR aName, IBandwidthGroup **aBandwidthGroup);
@@ -62,8 +62,8 @@ public:
// public internal methods
- HRESULT loadSettings(const settings::IoSettings &data);
- HRESULT saveSettings(settings::IoSettings &data);
+ HRESULT loadSettings(const settings::IOSettings &data);
+ HRESULT saveSettings(settings::IOSettings &data);
void rollback();
void commit();
diff --git a/src/VBox/Main/include/BandwidthGroupImpl.h b/src/VBox/Main/include/BandwidthGroupImpl.h
index 3ceb5a2c6..98a6b86ce 100644
--- a/src/VBox/Main/include/BandwidthGroupImpl.h
+++ b/src/VBox/Main/include/BandwidthGroupImpl.h
@@ -43,7 +43,7 @@ public:
HRESULT init(BandwidthControl *aParent,
const Utf8Str &aName,
BandwidthGroupType_T aType,
- ULONG aMaxMbPerSec);
+ LONG64 aMaxBytesPerSec);
HRESULT init(BandwidthControl *aParent, BandwidthGroup *aThat, bool aReshare = false);
HRESULT initCopy(BandwidthControl *aParent, BandwidthGroup *aThat);
void uninit();
@@ -54,8 +54,8 @@ public:
STDMETHOD(COMGETTER(Name))(BSTR *aName);
STDMETHOD(COMGETTER(Type))(BandwidthGroupType_T *aType);
STDMETHOD(COMGETTER(Reference))(ULONG *aReferences);
- STDMETHOD(COMGETTER(MaxMbPerSec))(ULONG *aMaxMbPerSec);
- STDMETHOD(COMSETTER(MaxMbPerSec))(ULONG aMaxMbPerSec);
+ STDMETHOD(COMGETTER(MaxBytesPerSec))(LONG64 *aMaxBytesPerSec);
+ STDMETHOD(COMSETTER(MaxBytesPerSec))(LONG64 aMaxBytesPerSec);
// public methods only for internal purposes
void rollback();
@@ -64,7 +64,7 @@ public:
const Utf8Str &getName() const;
BandwidthGroupType_T getType() const;
- ULONG getMaxMbPerSec() const;
+ LONG64 getMaxBytesPerSec() const;
ULONG getReferences() const;
void reference();
diff --git a/src/VBox/Main/include/BusAssignmentManager.h b/src/VBox/Main/include/BusAssignmentManager.h
index e5b004deb..1938fe7c4 100644
--- a/src/VBox/Main/include/BusAssignmentManager.h
+++ b/src/VBox/Main/include/BusAssignmentManager.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -32,37 +32,37 @@ private:
BusAssignmentManager();
virtual ~BusAssignmentManager();
- HRESULT assignPciDeviceImpl(const char* pszDevName, PCFGMNODE pCfg, PciBusAddress& GuestAddress, PciBusAddress HostAddress, bool fGuestAddressRequired = false);
+ HRESULT assignPCIDeviceImpl(const char* pszDevName, PCFGMNODE pCfg, PCIBusAddress& GuestAddress, PCIBusAddress HostAddress, bool fGuestAddressRequired = false);
public:
static BusAssignmentManager* createInstance(ChipsetType_T chipsetType);
virtual void AddRef();
virtual void Release();
- virtual HRESULT assignHostPciDevice(const char* pszDevName, PCFGMNODE pCfg, PciBusAddress HostAddress, PciBusAddress& GuestAddress, bool fAddressRequired = false)
+ virtual HRESULT assignHostPCIDevice(const char* pszDevName, PCFGMNODE pCfg, PCIBusAddress HostAddress, PCIBusAddress& GuestAddress, bool fAddressRequired = false)
{
- return assignPciDeviceImpl(pszDevName, pCfg, GuestAddress, HostAddress, fAddressRequired);
+ return assignPCIDeviceImpl(pszDevName, pCfg, GuestAddress, HostAddress, fAddressRequired);
}
- virtual HRESULT assignPciDevice(const char* pszDevName, PCFGMNODE pCfg, PciBusAddress& Address, bool fAddressRequired = false)
+ virtual HRESULT assignPCIDevice(const char* pszDevName, PCFGMNODE pCfg, PCIBusAddress& Address, bool fAddressRequired = false)
{
- PciBusAddress HostAddress;
- return assignPciDeviceImpl(pszDevName, pCfg, Address, HostAddress, fAddressRequired);
+ PCIBusAddress HostAddress;
+ return assignPCIDeviceImpl(pszDevName, pCfg, Address, HostAddress, fAddressRequired);
}
- virtual HRESULT assignPciDevice(const char* pszDevName, PCFGMNODE pCfg)
+ virtual HRESULT assignPCIDevice(const char* pszDevName, PCFGMNODE pCfg)
{
- PciBusAddress GuestAddress;
- PciBusAddress HostAddress;
- return assignPciDeviceImpl(pszDevName, pCfg, GuestAddress, HostAddress, false);
+ PCIBusAddress GuestAddress;
+ PCIBusAddress HostAddress;
+ return assignPCIDeviceImpl(pszDevName, pCfg, GuestAddress, HostAddress, false);
}
- virtual bool findPciAddress(const char* pszDevName, int iInstance, PciBusAddress& Address);
- virtual bool hasPciDevice(const char* pszDevName, int iInstance)
+ virtual bool findPCIAddress(const char* pszDevName, int iInstance, PCIBusAddress& Address);
+ virtual bool hasPCIDevice(const char* pszDevName, int iInstance)
{
- PciBusAddress Address;
- return findPciAddress(pszDevName, iInstance, Address);
+ PCIBusAddress Address;
+ return findPCIAddress(pszDevName, iInstance, Address);
}
- virtual void listAttachedPciDevices(ComSafeArrayOut(IPciDeviceAttachment*, aAttached));
+ virtual void listAttachedPCIDevices(ComSafeArrayOut(IPCIDeviceAttachment*, aAttached));
};
#endif // __BusAssignmentManager_h
diff --git a/src/VBox/Main/include/ConsoleImpl.h b/src/VBox/Main/include/ConsoleImpl.h
index edeba9ce6..2b2f19d0f 100644
--- a/src/VBox/Main/include/ConsoleImpl.h
+++ b/src/VBox/Main/include/ConsoleImpl.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -19,7 +19,6 @@
#define ____H_CONSOLEIMPL
#include "VirtualBoxBase.h"
-#include "SchemaDefs.h"
#include "VBox/com/array.h"
#include "EventImpl.h"
@@ -34,6 +33,7 @@ class RemoteUSBDevice;
class SharedFolder;
class VRDEServerInfo;
class AudioSniffer;
+class Nvram;
#ifdef VBOX_WITH_USB_VIDEO
class UsbWebcamInterface;
#endif
@@ -63,6 +63,7 @@ struct VUSBIRHCONFIG;
typedef struct VUSBIRHCONFIG *PVUSBIRHCONFIG;
#include <list>
+#include <vector>
// defines
///////////////////////////////////////////////////////////////////////////////
@@ -113,7 +114,7 @@ public:
void FinalRelease();
// public initializers/uninitializers for internal purposes only
- HRESULT init(IMachine *aMachine, IInternalMachineControl *aControl);
+ HRESULT init(IMachine *aMachine, IInternalMachineControl *aControl, LockType_T aLockType);
void uninit();
// IConsole properties
@@ -129,7 +130,7 @@ public:
STDMETHOD(COMGETTER(VRDEServerInfo))(IVRDEServerInfo **aVRDEServerInfo);
STDMETHOD(COMGETTER(SharedFolders))(ComSafeArrayOut(ISharedFolder *, aSharedFolders));
STDMETHOD(COMGETTER(EventSource)) (IEventSource ** aEventSource);
- STDMETHOD(COMGETTER(AttachedPciDevices))(ComSafeArrayOut(IPciDeviceAttachment *, aAttachments));
+ STDMETHOD(COMGETTER(AttachedPCIDevices))(ComSafeArrayOut(IPCIDeviceAttachment *, aAttachments));
STDMETHOD(COMGETTER(UseHostClipboard))(BOOL *aUseHostClipboard);
STDMETHOD(COMSETTER(UseHostClipboard))(BOOL aUseHostClipboard);
@@ -196,6 +197,8 @@ public:
HRESULT onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce);
HRESULT onCPUChange(ULONG aCPU, BOOL aRemove);
HRESULT onCPUExecutionCapChange(ULONG aExecutionCap);
+ HRESULT onClipboardModeChange(ClipboardMode_T aClipboardMode);
+ HRESULT onDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode);
HRESULT onVRDEServerChange(BOOL aRestart);
HRESULT onUSBControllerChange();
HRESULT onSharedFolderChange(BOOL aGlobal);
@@ -235,18 +238,19 @@ public:
void VRDPInterceptClipboard(uint32_t u32ClientId);
void processRemoteUSBDevices(uint32_t u32ClientId, VRDEUSBDEVICEDESC *pDevList, uint32_t cbDevList, bool fDescExt);
- void reportGuestStatistics(ULONG aValidStats, ULONG aCpuUser,
+ void reportVmStatistics(ULONG aValidStats, ULONG aCpuUser,
ULONG aCpuKernel, ULONG aCpuIdle,
ULONG aMemTotal, ULONG aMemFree,
ULONG aMemBalloon, ULONG aMemShared,
ULONG aMemCache, ULONG aPageTotal,
ULONG aAllocVMM, ULONG aFreeVMM,
- ULONG aBalloonedVMM, ULONG aSharedVMM)
+ ULONG aBalloonedVMM, ULONG aSharedVMM,
+ ULONG aVmNetRx, ULONG aVmNetTx)
{
- mControl->ReportGuestStatistics(aValidStats, aCpuUser, aCpuKernel, aCpuIdle,
- aMemTotal, aMemFree, aMemBalloon, aMemShared,
- aMemCache, aPageTotal, aAllocVMM, aFreeVMM,
- aBalloonedVMM, aSharedVMM);
+ mControl->ReportVmStatistics(aValidStats, aCpuUser, aCpuKernel, aCpuIdle,
+ aMemTotal, aMemFree, aMemBalloon, aMemShared,
+ aMemCache, aPageTotal, aAllocVMM, aFreeVMM,
+ aBalloonedVMM, aSharedVMM, aVmNetRx, aVmNetTx);
}
void enableVMMStatistics(BOOL aEnable);
@@ -272,8 +276,6 @@ public:
static HRESULT setErrorStatic(HRESULT aResultCode, const char *pcsz, ...);
HRESULT setInvalidMachineStateError();
- static HRESULT handleUnexpectedExceptions(RT_SRC_POS_DECL);
-
static const char *convertControllerTypeToDev(StorageControllerType_T enmCtrlType);
static HRESULT convertBusPortDeviceToLun(StorageBus_T enmBus, LONG port, LONG device, unsigned &uLun);
// Called from event listener
@@ -521,6 +523,7 @@ private:
static DECLCALLBACK(int) configConstructor(PVM pVM, void *pvConsole);
int configConstructorInner(PVM pVM, AutoWriteLock *pAlock);
int configCfgmOverlay(PVM pVM, IVirtualBox *pVirtualBox, IMachine *pMachine);
+ int configDumpAPISettingsTweaks(IVirtualBox *pVirtualBox, IMachine *pMachine);
int configMediumAttachment(PCFGMNODE pCtlInst,
const char *pcszDevice,
@@ -548,6 +551,7 @@ private:
unsigned uMergeSource,
unsigned uMergeTarget,
const char *pcszBwGroup,
+ bool fDiscard,
IMedium *pMedium,
MachineState_T aMachineState,
HRESULT *phrc);
@@ -573,7 +577,7 @@ private:
IMediumAttachment *aMediumAtt,
bool fForce);
- HRESULT attachRawPciDevices(PVM pVM, BusAssignmentManager *BusMgr, PCFGMNODE pDevices);
+ HRESULT attachRawPCIDevices(PVM pVM, BusAssignmentManager *BusMgr, PCFGMNODE pDevices);
void attachStatusDriver(PCFGMNODE pCtlInst, PPDMLED *papLeds,
uint64_t uFirst, uint64_t uLast,
Console::MediumAttachmentMap *pmapMediumAttachments,
@@ -584,7 +588,7 @@ private:
PCFGMNODE pLunL0, PCFGMNODE pInst,
bool fAttachDetach, bool fIgnoreConnectFailure);
- static DECLCALLBACK(int) configGuestProperties(void *pvConsole);
+ static DECLCALLBACK(int) configGuestProperties(void *pvConsole, PVM pVM);
static DECLCALLBACK(int) configGuestControl(void *pvConsole);
static DECLCALLBACK(void) vmstateChangeCallback(PVM aVM, VMSTATE aState,
VMSTATE aOldState, void *aUser);
@@ -600,13 +604,16 @@ private:
unsigned uInstance, unsigned uLun,
INetworkAdapter *aNetworkAdapter);
+ void changeClipboardMode(ClipboardMode_T aClipboardMode);
+ void changeDragAndDropMode(DragAndDropMode_T aDragAndDropMode);
+
#ifdef VBOX_WITH_USB
HRESULT attachUSBDevice(IUSBDevice *aHostDevice, ULONG aMaskedIfs);
- HRESULT detachUSBDevice(USBDeviceList::iterator &aIt);
+ HRESULT detachUSBDevice(const ComObjPtr<OUSBDevice> &aHostDevice);
static DECLCALLBACK(int) usbAttachCallback(Console *that, PVM pVM, IUSBDevice *aHostDevice, PCRTUUID aUuid,
- bool aRemote, const char *aAddress, ULONG aMaskedIfs);
- static DECLCALLBACK(int) usbDetachCallback(Console *that, PVM pVM, USBDeviceList::iterator *aIt, PCRTUUID aUuid);
+ bool aRemote, const char *aAddress, void *pvRemoteBackend, USHORT aPortVersion, ULONG aMaskedIfs);
+ static DECLCALLBACK(int) usbDetachCallback(Console *that, PVM pVM, PCRTUUID aUuid);
#endif
static DECLCALLBACK(int) attachStorageDevice(Console *pThis,
@@ -684,6 +691,9 @@ private:
void guestPropertiesVRDPUpdateActiveClient(uint32_t u32ClientId);
void guestPropertiesVRDPUpdateClientAttach(uint32_t u32ClientId, bool fAttached);
void guestPropertiesVRDPUpdateNameChange(uint32_t u32ClientId, const char *pszName);
+ void guestPropertiesVRDPUpdateIPAddrChange(uint32_t u32ClientId, const char *pszIPAddr);
+ void guestPropertiesVRDPUpdateLocationChange(uint32_t u32ClientId, const char *pszLocation);
+ void guestPropertiesVRDPUpdateOtherInfoChange(uint32_t u32ClientId, const char *pszOtherInfo);
void guestPropertiesVRDPUpdateDisconnect(uint32_t u32ClientId);
#endif
@@ -713,6 +723,9 @@ private:
const ComObjPtr<Display> mDisplay;
const ComObjPtr<MachineDebugger> mDebugger;
const ComObjPtr<VRDEServerInfo> mVRDEServerInfo;
+ /** This can safely be used without holding any locks.
+ * An AutoCaller suffices to prevent it being destroy while in use and
+ * internally there is a lock providing the necessary serialization. */
const ComObjPtr<EventSource> mEventSource;
#ifdef VBOX_WITH_EXTPACK
const ComObjPtr<ExtPackManager> mptrExtPackManager;
@@ -755,10 +768,12 @@ private:
* NetworkAdapter. This is needed to change the network attachment
* dynamically.
*/
- NetworkAttachmentType_T meAttachmentType[SchemaDefs::NetworkAdapterCount];
+ typedef std::vector<NetworkAttachmentType_T> NetworkAttachmentTypeVector;
+ NetworkAttachmentTypeVector meAttachmentType;
VMMDev * m_pVMMDev;
AudioSniffer * const mAudioSniffer;
+ Nvram * const mNvram;
#ifdef VBOX_WITH_USB_VIDEO
UsbWebcamInterface * const mUsbWebcamInterface;
#endif
@@ -783,7 +798,7 @@ private:
};
DeviceType_T maStorageDevType[cLedStorage];
PPDMLED mapStorageLeds[cLedStorage];
- PPDMLED mapNetworkLeds[SchemaDefs::NetworkAdapterCount];
+ PPDMLED mapNetworkLeds[36]; /**< @todo adapt this to the maximum network card count */
PPDMLED mapSharedFolderLed;
PPDMLED mapUSBLed[2];
@@ -811,6 +826,10 @@ private:
* operation before starting. */
ComObjPtr<Progress> mptrCancelableProgress;
+ /* The purpose of caching of some events is probably in order to
+ automatically fire them at new event listeners. However, there is no
+ (longer?) any code making use of this... */
+#ifdef CONSOLE_WITH_EVENT_CACHE
struct
{
/** OnMousePointerShapeChange() cache */
@@ -824,8 +843,7 @@ private:
uint32_t width;
uint32_t height;
com::SafeArray<BYTE> shape;
- }
- mpsc;
+ } mpsc;
/** OnMouseCapabilityChange() cache */
struct
@@ -834,8 +852,7 @@ private:
BOOL supportsAbsolute;
BOOL supportsRelative;
BOOL needsHostCursor;
- }
- mcc;
+ } mcc;
/** OnKeyboardLedsChange() cache */
struct
@@ -844,20 +861,20 @@ private:
bool numLock;
bool capsLock;
bool scrollLock;
- }
- klc;
+ } klc;
void clear()
{
- /* We cannot do memset() on mpsc to avoid cleaning shape's vtable */
+ RT_ZERO(mcc);
+ RT_ZERO(klc);
+
+ /* We cannot RT_ZERO mpsc because of shape's vtable. */
mpsc.shape.setNull();
mpsc.valid = mpsc.visible = mpsc.alpha = false;
mpsc.xHot = mpsc.yHot = mpsc.width = mpsc.height = 0;
- ::memset(&mcc, 0, sizeof mcc);
- ::memset(&klc, 0, sizeof klc);
}
- }
- mCallbackData;
+ } mCallbackData;
+#endif
ComPtr<IEventListener> mVmListener;
friend struct VMTask;
diff --git a/src/VBox/Main/include/ConsoleVRDPServer.h b/src/VBox/Main/include/ConsoleVRDPServer.h
index 1651f49af..30980d9c1 100644
--- a/src/VBox/Main/include/ConsoleVRDPServer.h
+++ b/src/VBox/Main/include/ConsoleVRDPServer.h
@@ -24,9 +24,12 @@
#include <VBox/VBoxAuth.h>
#include <VBox/RemoteDesktop/VRDEImage.h>
+#include <VBox/RemoteDesktop/VRDEMousePtr.h>
#include <VBox/RemoteDesktop/VRDESCard.h>
+#include <VBox/RemoteDesktop/VRDETSMF.h>
#include <VBox/HostServices/VBoxClipboardExt.h>
+#include <VBox/HostServices/VBoxHostChannel.h>
#include "SchemaDefs.h"
@@ -85,6 +88,7 @@ public:
void EnableConnections (void);
void DisconnectClient (uint32_t u32ClientId, bool fReconnect);
+ int MousePointer(BOOL alpha, ULONG xHot, ULONG yHot, ULONG width, ULONG height, const uint8_t *pu8Shape);
void MousePointerUpdate (const VRDECOLORPOINTER *pPointer);
void MousePointerHide (void);
@@ -261,6 +265,8 @@ private:
uint32_t u32Id,
void *pvData,
uint32_t cbData);
+ /* Mouse pointer interface. */
+ VRDEMOUSEPTRINTERFACE m_interfaceMousePtr;
/* Smartcard interface. */
VRDESCARDINTERFACE m_interfaceSCard;
@@ -275,6 +281,29 @@ private:
uint32_t u32Function,
void *pvData,
uint32_t cbData);
+
+ /* TSMF interface. */
+ VRDETSMFINTERFACE m_interfaceTSMF;
+ VRDETSMFCALLBACKS m_interfaceCallbacksTSMF;
+ static DECLCALLBACK(void) VRDETSMFCbNotify(void *pvContext,
+ uint32_t u32Notification,
+ void *pvChannel,
+ const void *pvParm,
+ uint32_t cbParm);
+ void setupTSMF(void);
+
+ static DECLCALLBACK(int) tsmfHostChannelAttach(void *pvProvider, void **ppvInstance, uint32_t u32Flags,
+ VBOXHOSTCHANNELCALLBACKS *pCallbacks, void *pvCallbacks);
+ static DECLCALLBACK(void) tsmfHostChannelDetach(void *pvInstance);
+ static DECLCALLBACK(int) tsmfHostChannelSend(void *pvInstance, const void *pvData, uint32_t cbData);
+ static DECLCALLBACK(int) tsmfHostChannelRecv(void *pvInstance, void *pvData, uint32_t cbData,
+ uint32_t *pcbReturned, uint32_t *pcbRemaining);
+ static DECLCALLBACK(int) tsmfHostChannelControl(void *pvInstance, uint32_t u32Code,
+ const void *pvParm, uint32_t cbParm,
+ const void *pvData, uint32_t cbData, uint32_t *pcbDataReturned);
+ int tsmfLock(void);
+ void tsmfUnlock(void);
+ RTCRITSECT mTSMFLock;
};
diff --git a/src/VBox/Main/include/DisplayImpl.h b/src/VBox/Main/include/DisplayImpl.h
index ab024cf09..1f7837007 100644
--- a/src/VBox/Main/include/DisplayImpl.h
+++ b/src/VBox/Main/include/DisplayImpl.h
@@ -27,6 +27,7 @@
#include <VBox/VBoxVideo.h>
class Console;
+struct VIDEORECCONTEXT;
enum {
ResizeStatus_Void,
@@ -160,7 +161,7 @@ public:
STDMETHOD(GetScreenResolution)(ULONG aScreenId, ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel);
STDMETHOD(SetFramebuffer)(ULONG aScreenId, IFramebuffer *aFramebuffer);
STDMETHOD(GetFramebuffer)(ULONG aScreenId, IFramebuffer **aFramebuffer, LONG *aXOrigin, LONG *aYOrigin);
- STDMETHOD(SetVideoModeHint)(ULONG width, ULONG height, ULONG bitsPerPixel, ULONG display);
+ STDMETHOD(SetVideoModeHint)(ULONG aDisplay, BOOL aEnabled, BOOL aChangeOrigin, LONG aOriginX, LONG aOriginY, ULONG aWidth, ULONG aHeight, ULONG aBitsPerPixel);
STDMETHOD(TakeScreenShot)(ULONG aScreenId, BYTE *address, ULONG width, ULONG height);
STDMETHOD(TakeScreenShotToArray)(ULONG aScreenId, ULONG width, ULONG height, ComSafeArrayOut(BYTE, aScreenData));
STDMETHOD(TakeScreenShotPNGToArray)(ULONG aScreenId, ULONG width, ULONG height, ComSafeArrayOut(BYTE, aScreenData));
@@ -171,6 +172,8 @@ public:
STDMETHOD(CompleteVHWACommand)(BYTE *pCommand);
+ STDMETHOD(ViewportChanged)(ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height);
+
static const PDMDRVREG DrvReg;
private:
@@ -291,6 +294,10 @@ private:
#ifdef VBOX_WITH_HGSMI
volatile uint32_t mu32UpdateVBVAFlags;
#endif
+
+#ifdef VBOX_WITH_VPX
+ VIDEORECCONTEXT *mpVideoRecContext;
+#endif
};
void gdImageCopyResampled (uint8_t *dst, uint8_t *src,
diff --git a/src/VBox/Main/include/DisplayUtils.h b/src/VBox/Main/include/DisplayUtils.h
index ff928aa68..6c4a9b163 100644
--- a/src/VBox/Main/include/DisplayUtils.h
+++ b/src/VBox/Main/include/DisplayUtils.h
@@ -23,7 +23,9 @@ using namespace com;
#define sSSMDisplayVer2 0x00010002
#define sSSMDisplayVer3 0x00010003
-int readSavedGuestSize(const Utf8Str &strStateFilePath, uint32_t u32ScreenId, uint32_t *pu32Width, uint32_t *pu32Height);
+int readSavedGuestScreenInfo(const Utf8Str &strStateFilePath, uint32_t u32ScreenId,
+ uint32_t *pu32OriginX, uint32_t *pu32OriginY,
+ uint32_t *pu32Width, uint32_t *pu32Height, uint16_t *pu16Flags);
int readSavedDisplayScreenshot(const Utf8Str &strStateFilePath, uint32_t u32Type, uint8_t **ppu8Data, uint32_t *pcbData, uint32_t *pu32Width, uint32_t *pu32Height);
void freeSavedDisplayScreenshot(uint8_t *pu8Data);
diff --git a/src/VBox/Main/include/EventImpl.h b/src/VBox/Main/include/EventImpl.h
index ad795595c..e2979ce64 100644
--- a/src/VBox/Main/include/EventImpl.h
+++ b/src/VBox/Main/include/EventImpl.h
@@ -1,10 +1,10 @@
+/* $Id: EventImpl.h $ */
/** @file
- *
* VirtualBox COM IEvent implementation
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Main/include/ExtPackManagerImpl.h b/src/VBox/Main/include/ExtPackManagerImpl.h
index 08ca31676..c3f9a78d8 100644
--- a/src/VBox/Main/include/ExtPackManagerImpl.h
+++ b/src/VBox/Main/include/ExtPackManagerImpl.h
@@ -54,6 +54,7 @@ public:
STDMETHOD(COMGETTER(Description))(BSTR *a_pbstrDescription);
STDMETHOD(COMGETTER(Version))(BSTR *a_pbstrVersion);
STDMETHOD(COMGETTER(Revision))(ULONG *a_puRevision);
+ STDMETHOD(COMGETTER(Edition))(BSTR *a_pbstrEdition);
STDMETHOD(COMGETTER(VRDEModule))(BSTR *a_pbstrVrdeModule);
STDMETHOD(COMGETTER(PlugIns))(ComSafeArrayOut(IExtPackPlugIn *, a_paPlugIns));
STDMETHOD(COMGETTER(Usable))(BOOL *a_pfUsable);
@@ -117,6 +118,7 @@ public:
STDMETHOD(COMGETTER(Description))(BSTR *a_pbstrDescription);
STDMETHOD(COMGETTER(Version))(BSTR *a_pbstrVersion);
STDMETHOD(COMGETTER(Revision))(ULONG *a_puRevision);
+ STDMETHOD(COMGETTER(Edition))(BSTR *a_pbstrEdition);
STDMETHOD(COMGETTER(VRDEModule))(BSTR *a_pbstrVrdeModule);
STDMETHOD(COMGETTER(PlugIns))(ComSafeArrayOut(IExtPackPlugIn *, a_paPlugIns));
STDMETHOD(COMGETTER(Usable))(BOOL *a_pfUsable);
diff --git a/src/VBox/Main/include/ExtPackUtil.h b/src/VBox/Main/include/ExtPackUtil.h
index d7e3c253d..0fd97bf03 100644
--- a/src/VBox/Main/include/ExtPackUtil.h
+++ b/src/VBox/Main/include/ExtPackUtil.h
@@ -112,14 +112,14 @@ typedef VBOXEXTPACKDESC const *PCVBOXEXTPACKDESC;
void VBoxExtPackInitDesc(PVBOXEXTPACKDESC a_pExtPackDesc);
-RTCString *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
-RTCString *VBoxExtPackLoadDescFromVfsFile(RTVFSFILE hVfsFile, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
-RTCString *VBoxExtPackExtractNameFromTarballPath(const char *pszTarball);
+RTCString *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
+RTCString *VBoxExtPackLoadDescFromVfsFile(RTVFSFILE hVfsFile, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
+RTCString *VBoxExtPackExtractNameFromTarballPath(const char *pszTarball);
void VBoxExtPackFreeDesc(PVBOXEXTPACKDESC a_pExtPackDesc);
bool VBoxExtPackIsValidName(const char *pszName);
bool VBoxExtPackIsValidMangledName(const char *pszMangledName, size_t cchMax = RTSTR_MAX);
-RTCString *VBoxExtPackMangleName(const char *pszName);
-RTCString *VBoxExtPackUnmangleName(const char *pszMangledName, size_t cbMax);
+RTCString *VBoxExtPackMangleName(const char *pszName);
+RTCString *VBoxExtPackUnmangleName(const char *pszMangledName, size_t cbMax);
int VBoxExtPackCalcDir(char *pszExtPackDir, size_t cbExtPackDir, const char *pszParentDir, const char *pszName);
bool VBoxExtPackIsValidVersionString(const char *pszVersion);
bool VBoxExtPackIsValidEditionString(const char *pszEdition);
diff --git a/src/VBox/Main/include/FramebufferImpl.h b/src/VBox/Main/include/FramebufferImpl.h
index 1ea5951a9..feebfcdd2 100644
--- a/src/VBox/Main/include/FramebufferImpl.h
+++ b/src/VBox/Main/include/FramebufferImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -25,8 +25,6 @@
class ATL_NO_VTABLE Framebuffer :
public VirtualBoxBase,
- public VirtualBoxSupportErrorInfoImpl<Framebuffer, IFramebuffer>,
- public VirtualBoxSupportTranslation<Framebuffer>,
VBOX_SCRIPTABLE_IMPL(IFramebuffer)
{
public:
@@ -72,10 +70,6 @@ public:
STDMETHOD(SetVisibleRegion)(BYTE *aRectangles, ULONG aCount) = 0;
STDMETHOD(ProcessVHWACommand)(BYTE *pCommand) = 0;
-
- // for VirtualBoxSupportErrorInfoImpl
- static const wchar_t *getComponentName() { return L"Framebuffer"; }
-
};
#endif // ____H_H_FRAMEBUFFERIMPL
diff --git a/src/VBox/Main/include/Global.h b/src/VBox/Main/include/Global.h
index e43aa7081..bfe53af4d 100644
--- a/src/VBox/Main/include/Global.h
+++ b/src/VBox/Main/include/Global.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008-2010 Oracle Corporation
+ * Copyright (C) 2008-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -18,9 +18,6 @@
#ifndef ____H_GLOBAL
#define ____H_GLOBAL
-/* generated header */
-#include "SchemaDefs.h"
-
/* interface definitions */
#include "VBox/com/VirtualBox.h"
@@ -38,6 +35,10 @@
#define VBOXOSHINT_HPET RT_BIT(6)
#define VBOXOSHINT_USBTABLET RT_BIT(7)
#define VBOXOSHINT_RTCUTC RT_BIT(8)
+#define VBOXOSHINT_ACCEL2D RT_BIT(9)
+#define VBOXOSHINT_ACCEL3D RT_BIT(10)
+#define VBOXOSHINT_FLOPPY RT_BIT(11)
+#define VBOXOSHINT_NOUSB RT_BIT(12)
/** The VBoxVRDP kludge extension pack name.
*
@@ -59,7 +60,7 @@ public:
{
const char *familyId; /* utf-8 */
const char *familyDescription; /* utf-8 */
- const char *id; /* utf-8 */
+ const char *id; /* utf-8, VM config file value */
const char *description; /* utf-8 */
const VBOXOSTYPE osType;
const uint32_t osHint;
@@ -76,11 +77,20 @@ public:
const AudioControllerType_T audioControllerType;
};
- static const OSType sOSTypes[SchemaDefs::OSTypeId_COUNT];
+ static const OSType sOSTypes[];
+ static uint32_t cOSTypes;
+ /**
+ * Maps VBOXOSTYPE to the OS type which is used in VM configs.
+ */
static const char *OSTypeId(VBOXOSTYPE aOSType);
/**
+ * Get the network adapter limit for each chipset type.
+ */
+ static uint32_t getMaxNetworkAdapters(ChipsetType_T aChipsetType);
+
+ /**
* Returns @c true if the given machine state is an online state. This is a
* recommended way to detect if the VM is online (being executed in a
* dedicated process) or not. Note that some online states are also
diff --git a/src/VBox/Main/include/GuestCtrlImplPrivate.h b/src/VBox/Main/include/GuestCtrlImplPrivate.h
index 6b32d788a..b8feac320 100644
--- a/src/VBox/Main/include/GuestCtrlImplPrivate.h
+++ b/src/VBox/Main/include/GuestCtrlImplPrivate.h
@@ -1,10 +1,10 @@
/** @file
*
- * VirtualBox Guest Control - Private data definitions / classes.
+ * Internal helpers/structures for guest control functionality.
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -18,7 +18,11 @@
#ifndef ____H_GUESTIMPLPRIVATE
#define ____H_GUESTIMPLPRIVATE
+#include <iprt/asm.h>
+#include <iprt/semaphore.h>
+
#include <VBox/com/com.h>
+#include <VBox/com/ErrorInfo.h>
#include <VBox/com/string.h>
#include <VBox/com/VirtualBox.h>
@@ -32,20 +36,304 @@ using namespace com;
using namespace guestControl;
#endif
-class Guest;
-class Progress;
+/** Maximum number of guest sessions a VM can have. */
+#define VBOX_GUESTCTRL_MAX_SESSIONS 32
+/** Maximum number of guest objects (processes, files, ...)
+ * a guest session can have. */
+#define VBOX_GUESTCTRL_MAX_OBJECTS _2K
+/** Maximum of callback contexts a guest process can have. */
+#define VBOX_GUESTCTRL_MAX_CONTEXTS _64K
+
+/** Builds a context ID out of the session ID, object ID and an
+ * increasing count. */
+#define VBOX_GUESTCTRL_CONTEXTID_MAKE(uSession, uObject, uCount) \
+ ( (uint32_t)((uSession) & 0x1f) << 27 \
+ | (uint32_t)((uObject) & 0x7ff) << 16 \
+ | (uint32_t)((uCount) & 0xffff) \
+ )
+/** Gets the session ID out of a context ID. */
+#define VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID) \
+ ((uContextID) >> 27)
+/** Gets the process ID out of a context ID. */
+#define VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(uContextID) \
+ (((uContextID) >> 16) & 0x7ff)
+/** Gets the conext count of a process out of a context ID. */
+#define VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID) \
+ ((uContextID) & 0xffff)
+
+/** Vector holding a process' CPU affinity. */
+typedef std::vector <LONG> ProcessAffinity;
+/** Vector holding process startup arguments. */
+typedef std::vector <Utf8Str> ProcessArguments;
+
+class GuestProcessStreamBlock;
+
+
+/**
+ * Base class for a all guest control callbacks/events.
+ */
+class GuestCtrlEvent
+{
+public:
+
+ GuestCtrlEvent(void);
+
+ virtual ~GuestCtrlEvent(void);
+
+ /** @todo Copy/comparison operator? */
+
+public:
+
+ int Cancel(void);
+
+ bool Canceled(void);
+
+ virtual void Destroy(void);
+
+ int Init(void);
+
+ virtual int Signal(int rc = VINF_SUCCESS);
+
+ int GetResultCode(void) { return mRC; }
+
+ int Wait(ULONG uTimeoutMS);
+
+protected:
+
+ /** Was the callback canceled? */
+ bool fCanceled;
+ /** Did the callback complete? */
+ bool fCompleted;
+ /** The event semaphore for triggering
+ * the actual event. */
+ RTSEMEVENT hEventSem;
+ /** The waiting mutex. */
+ RTSEMMUTEX hEventMutex;
+ /** Overall result code. */
+ int mRC;
+};
+
+
+/*
+ * Class representing a guest control callback.
+ */
+class GuestCtrlCallback : public GuestCtrlEvent
+{
+public:
+
+ GuestCtrlCallback(void);
+
+ GuestCtrlCallback(eVBoxGuestCtrlCallbackType enmType);
+
+ virtual ~GuestCtrlCallback(void);
+
+public:
+
+ void Destroy(void);
+
+ int Init(eVBoxGuestCtrlCallbackType enmType);
+
+ eVBoxGuestCtrlCallbackType GetCallbackType(void) { return mType; }
+
+ const void* GetDataRaw(void) const { return pvData; }
+
+ size_t GetDataSize(void) { return cbData; }
+
+ const void* GetPayloadRaw(void) const { return pvPayload; }
+
+ size_t GetPayloadSize(void) { return cbPayload; }
+
+ int SetData(const void *pvCallback, size_t cbCallback);
+
+ int SetPayload(const void *pvToWrite, size_t cbToWrite);
+
+protected:
+
+ /** Pointer to actual callback data. */
+ void *pvData;
+ /** Size of user-supplied data. */
+ size_t cbData;
+ /** The callback type. */
+ eVBoxGuestCtrlCallbackType mType;
+ /** Callback flags. */
+ uint32_t uFlags;
+ /** Payload which will be available on successful
+ * waiting (optional). */
+ void *pvPayload;
+ /** Size of the payload (optional). */
+ size_t cbPayload;
+};
+typedef std::map < uint32_t, GuestCtrlCallback* > GuestCtrlCallbacks;
+
+
+/*
+ * Class representing a guest control process waiting
+ * event.
+ */
+class GuestProcessWaitEvent : public GuestCtrlEvent
+{
+public:
+
+ GuestProcessWaitEvent(void);
+
+ GuestProcessWaitEvent(uint32_t uWaitFlags);
+
+ virtual ~GuestProcessWaitEvent(void);
+
+public:
+
+ void Destroy(void);
+
+ int Init(uint32_t uWaitFlags);
+
+ uint32_t GetWaitFlags(void) { return ASMAtomicReadU32(&mFlags); }
-/** Structure representing the "value" side of a "key=value" pair. */
+ ProcessWaitResult_T GetWaitResult(void) { return mResult; }
+
+ int GetWaitRc(void) { return mRC; }
+
+ int Signal(ProcessWaitResult_T enmResult, int rc = VINF_SUCCESS);
+
+protected:
+
+ /** The waiting flag(s). The specifies what to
+ * wait for. See ProcessWaitFlag_T. */
+ uint32_t mFlags;
+ /** Structure containing the overall result. */
+ ProcessWaitResult_T mResult;
+};
+
+
+/**
+ * Simple structure mantaining guest credentials.
+ */
+struct GuestCredentials
+{
+ Utf8Str mUser;
+ Utf8Str mPassword;
+ Utf8Str mDomain;
+};
+
+
+typedef std::vector <Utf8Str> GuestEnvironmentArray;
+class GuestEnvironment
+{
+public:
+
+ int BuildEnvironmentBlock(void **ppvEnv, size_t *pcbEnv, uint32_t *pcEnvVars);
+
+ void Clear(void);
+
+ int CopyFrom(const GuestEnvironmentArray &environment);
+
+ int CopyTo(GuestEnvironmentArray &environment);
+
+ static void FreeEnvironmentBlock(void *pvEnv);
+
+ Utf8Str Get(const Utf8Str &strKey);
+
+ Utf8Str Get(size_t nPos);
+
+ bool Has(const Utf8Str &strKey);
+
+ int Set(const Utf8Str &strKey, const Utf8Str &strValue);
+
+ int Set(const Utf8Str &strPair);
+
+ size_t Size(void);
+
+ int Unset(const Utf8Str &strKey);
+
+public:
+
+ GuestEnvironment& operator=(const GuestEnvironmentArray &that);
+
+ GuestEnvironment& operator=(const GuestEnvironment &that);
+
+protected:
+
+ int appendToEnvBlock(const char *pszEnv, void **ppvList, size_t *pcbList, uint32_t *pcEnvVars);
+
+protected:
+
+ std::map <Utf8Str, Utf8Str> mEnvironment;
+};
+
+
+/**
+ * Structure representing information of a
+ * file system object.
+ */
+struct GuestFsObjData
+{
+ /** Helper function to extract the data from
+ * a certin VBoxService tool's guest stream block. */
+ int FromLs(const GuestProcessStreamBlock &strmBlk);
+ int FromStat(const GuestProcessStreamBlock &strmBlk);
+
+ int64_t mAccessTime;
+ int64_t mAllocatedSize;
+ int64_t mBirthTime;
+ int64_t mChangeTime;
+ uint32_t mDeviceNumber;
+ Utf8Str mFileAttrs;
+ uint32_t mGenerationID;
+ uint32_t mGID;
+ Utf8Str mGroupName;
+ uint32_t mNumHardLinks;
+ int64_t mModificationTime;
+ Utf8Str mName;
+ int64_t mNodeID;
+ uint32_t mNodeIDDevice;
+ int64_t mObjectSize;
+ FsObjType_T mType;
+ uint32_t mUID;
+ uint32_t mUserFlags;
+ Utf8Str mUserName;
+ Utf8Str mACL;
+};
+
+
+/**
+ * Structure for keeping all the relevant process
+ * starting parameters around.
+ */
+class GuestProcessStartupInfo
+{
+public:
+
+ GuestProcessStartupInfo(void)
+ : mFlags(ProcessCreateFlag_None),
+ mTimeoutMS(30 * 1000 /* 30s timeout by default */),
+ mPriority(ProcessPriority_Default) { }
+
+ /** The process' friendly name. */
+ Utf8Str mName;
+ /** The actual command to execute. */
+ Utf8Str mCommand;
+ ProcessArguments mArguments;
+ GuestEnvironment mEnvironment;
+ /** Process creation flags. */
+ uint32_t mFlags;
+ ULONG mTimeoutMS;
+ ProcessPriority_T mPriority;
+ ProcessAffinity mAffinity;
+};
+
+
+/**
+ * Class representing the "value" side of a "key=value" pair.
+ */
class GuestProcessStreamValue
{
public:
- GuestProcessStreamValue() { }
+ GuestProcessStreamValue(void) { }
GuestProcessStreamValue(const char *pszValue)
: mValue(pszValue) {}
GuestProcessStreamValue(const GuestProcessStreamValue& aThat)
- : mValue(aThat.mValue) {}
+ : mValue(aThat.mValue) { }
Utf8Str mValue;
};
@@ -65,31 +353,31 @@ class GuestProcessStreamBlock
{
public:
- GuestProcessStreamBlock();
+ GuestProcessStreamBlock(void);
- //GuestProcessStreamBlock(GuestProcessStreamBlock &);
-
- virtual ~GuestProcessStreamBlock();
+ virtual ~GuestProcessStreamBlock(void);
public:
- void Clear();
+ void Clear(void);
#ifdef DEBUG
- void Dump();
+ void DumpToLog(void) const;
#endif
- int GetInt64Ex(const char *pszKey, int64_t *piVal);
+ int GetInt64Ex(const char *pszKey, int64_t *piVal) const;
+
+ int64_t GetInt64(const char *pszKey) const;
- int64_t GetInt64(const char *pszKey);
+ size_t GetCount(void) const;
- size_t GetCount();
+ const char* GetString(const char *pszKey) const;
- const char* GetString(const char *pszKey);
+ int GetUInt32Ex(const char *pszKey, uint32_t *puVal) const;
- int GetUInt32Ex(const char *pszKey, uint32_t *puVal);
+ uint32_t GetUInt32(const char *pszKey) const;
- uint32_t GetUInt32(const char *pszKey);
+ bool IsEmpty(void) { return m_mapPairs.empty(); }
int SetValue(const char *pszKey, const char *pszValue);
@@ -144,6 +432,9 @@ protected:
BYTE *m_pbBuffer;
};
+class Guest;
+class Progress;
+
class GuestTask
{
diff --git a/src/VBox/Main/include/GuestDirEntryImpl.h b/src/VBox/Main/include/GuestDirEntryImpl.h
deleted file mode 100644
index 8d56267fa..000000000
--- a/src/VBox/Main/include/GuestDirEntryImpl.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* $Id: GuestDirEntryImpl.h $ */
-/** @file
- * VirtualBox Main - interface for guest directory entries, VBoxC.
- */
-
-/*
- * Copyright (C) 2011 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#ifndef ____H_GUESTDIRENTRYIMPL
-#define ____H_GUESTDIRENTRYIMPL
-
-#include "VirtualBoxBase.h"
-
-class Guest;
-class GuestProcessStreamBlock;
-
-/**
- * A directory entry.
- */
-class ATL_NO_VTABLE GuestDirEntry :
- public VirtualBoxBase,
- VBOX_SCRIPTABLE_IMPL(IGuestDirEntry)
-{
-public:
- /** @name COM and internal init/term/mapping cruft.
- * @{ */
- VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(GuestDirEntry, IGuestDirEntry)
- DECLARE_NOT_AGGREGATABLE(GuestDirEntry)
- DECLARE_PROTECT_FINAL_CONSTRUCT()
- BEGIN_COM_MAP(GuestDirEntry)
- VBOX_DEFAULT_INTERFACE_ENTRIES(IGuestDirEntry)
- END_COM_MAP()
- DECLARE_EMPTY_CTOR_DTOR(GuestDirEntry)
-
- HRESULT init(Guest *aParent, GuestProcessStreamBlock &streamBlock);
- void uninit();
- HRESULT FinalConstruct();
- void FinalRelease();
- /** @} */
-
- /** @name IGuestDirEntry properties
- * @{ */
- STDMETHOD(COMGETTER(NodeId))(LONG64 *aNodeId);
- STDMETHOD(COMGETTER(Name))(BSTR *aName);
- STDMETHOD(COMGETTER(Type))(GuestDirEntryType_T *aType);
- /** @} */
-
-public:
- /** @name Public internal methods
- * @{ */
- static GuestDirEntryType_T fileTypeToEntryType(const char *pszFileType);
- /** @} */
-
-private:
- struct Data
- {
- /** The entry's node ID. */
- LONG64 mNodeId;
- /** The entry's name. */
- Bstr mName;
- /** The entry's type. */
- GuestDirEntryType_T mType;
- } mData;
-};
-
-#endif /* !____H_GUESTDIRENTRYIMPL */
-
diff --git a/src/VBox/Main/include/GuestDirectoryImpl.h b/src/VBox/Main/include/GuestDirectoryImpl.h
new file mode 100644
index 000000000..62981067f
--- /dev/null
+++ b/src/VBox/Main/include/GuestDirectoryImpl.h
@@ -0,0 +1,82 @@
+
+/* $Id: GuestDirectoryImpl.h $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTDIRECTORYIMPL
+#define ____H_GUESTDIRECTORYIMPL
+
+#include "VirtualBoxBase.h"
+#include "GuestProcessImpl.h"
+
+class GuestSession;
+
+/**
+ * TODO
+ */
+class ATL_NO_VTABLE GuestDirectory :
+ public VirtualBoxBase,
+ VBOX_SCRIPTABLE_IMPL(IGuestDirectory)
+{
+public:
+ /** @name COM and internal init/term/mapping cruft.
+ * @{ */
+ VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(GuestDirectory, IGuestDirectory)
+ DECLARE_NOT_AGGREGATABLE(GuestDirectory)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+ BEGIN_COM_MAP(GuestDirectory)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IGuestDirectory)
+ COM_INTERFACE_ENTRY(IDirectory)
+ END_COM_MAP()
+ DECLARE_EMPTY_CTOR_DTOR(GuestDirectory)
+
+ int init(GuestSession *aSession, const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags);
+ void uninit(void);
+ HRESULT FinalConstruct(void);
+ void FinalRelease(void);
+ /** @} */
+
+ /** @name IDirectory interface.
+ * @{ */
+ STDMETHOD(COMGETTER(DirectoryName))(BSTR *aName);
+ STDMETHOD(COMGETTER(Filter))(BSTR *aFilter);
+ STDMETHOD(Close)(void);
+ STDMETHOD(Read)(IFsObjInfo **aInfo);
+ /** @} */
+
+public:
+ /** @name Public internal methods.
+ * @{ */
+ /** @} */
+
+private:
+
+ /** @name Private internal methods.
+ * @{ */
+ /** @} */
+
+ struct Data
+ {
+ GuestSession *mSession;
+ Utf8Str mName;
+ Utf8Str mFilter;
+ uint32_t mFlags;
+ GuestProcessTool mProcessTool;
+ } mData;
+};
+
+#endif /* !____H_GUESTDIRECTORYIMPL */
+
diff --git a/src/VBox/Main/include/GuestDnDImpl.h b/src/VBox/Main/include/GuestDnDImpl.h
new file mode 100644
index 000000000..e65657cc7
--- /dev/null
+++ b/src/VBox/Main/include/GuestDnDImpl.h
@@ -0,0 +1,53 @@
+/** @file
+ * Definition of GuestDnD
+ */
+
+/*
+ * Copyright (C) 2011-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTDND
+#define ____H_GUESTDND
+
+/* Forward declaration of the d-pointer. */
+class GuestDnDPrivate;
+
+class GuestDnD
+{
+public:
+ GuestDnD(const ComObjPtr<Guest>& pGuest);
+ ~GuestDnD();
+
+ /* Host -> Guest */
+ HRESULT dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction);
+ HRESULT dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction);
+ HRESULT dragHGLeave(ULONG uScreenId);
+ HRESULT dragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction);
+ HRESULT dragHGPutData(ULONG uScreenId, IN_BSTR wstrFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress);
+
+ /* Guest -> Host */
+ HRESULT dragGHPending(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction);
+ HRESULT dragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, IProgress **ppProgress);
+ HRESULT dragGHGetData(ComSafeArrayOut(BYTE, data));
+
+ /* Guest response */
+ static DECLCALLBACK(int) notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
+
+private:
+
+ /* d-pointer */
+ GuestDnDPrivate *d_ptr;
+
+ friend class GuestDnDPrivate;
+};
+
+#endif /* ____H_GUESTDND */
+
diff --git a/src/VBox/Main/include/GuestFileImpl.h b/src/VBox/Main/include/GuestFileImpl.h
new file mode 100644
index 000000000..cea13081d
--- /dev/null
+++ b/src/VBox/Main/include/GuestFileImpl.h
@@ -0,0 +1,96 @@
+
+/* $Id: GuestFileImpl.h $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTFILEIMPL
+#define ____H_GUESTFILEIMPL
+
+#include "VirtualBoxBase.h"
+
+#include "GuestFsObjInfoImpl.h"
+
+class GuestSession;
+class GuestProcess;
+
+/**
+ * TODO
+ */
+class ATL_NO_VTABLE GuestFile :
+ public VirtualBoxBase,
+ VBOX_SCRIPTABLE_IMPL(IGuestFile)
+{
+public:
+ /** @name COM and internal init/term/mapping cruft.
+ * @{ */
+ VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(GuestFile, IGuestFile)
+ DECLARE_NOT_AGGREGATABLE(GuestFile)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+ BEGIN_COM_MAP(GuestFile)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IGuestFile)
+ COM_INTERFACE_ENTRY(IFile)
+ END_COM_MAP()
+ DECLARE_EMPTY_CTOR_DTOR(GuestFile)
+
+ int init(GuestSession *pSession, const Utf8Str &strPath, const Utf8Str &strOpenMode, const Utf8Str &strDisposition, uint32_t uCreationMode, int64_t iOffset, int *pGuestRc);
+ void uninit(void);
+ HRESULT FinalConstruct(void);
+ void FinalRelease(void);
+ /** @} */
+
+ /** @name IFile interface.
+ * @{ */
+ STDMETHOD(COMGETTER(CreationMode))(ULONG *aCreationMode);
+ STDMETHOD(COMGETTER(Disposition))(ULONG *aDisposition);
+ STDMETHOD(COMGETTER(FileName))(BSTR *aFileName);
+ STDMETHOD(COMGETTER(InitialSize))(LONG64 *aInitialSize);
+ STDMETHOD(COMGETTER(Offset))(LONG64 *aOffset);
+ STDMETHOD(COMGETTER(OpenMode))(ULONG *aOpenMode);
+
+ STDMETHOD(Close)(void);
+ STDMETHOD(QueryInfo)(IFsObjInfo **aInfo);
+ STDMETHOD(Read)(ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData));
+ STDMETHOD(ReadAt)(LONG64 aOffset, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData));
+ STDMETHOD(Seek)(LONG64 aOffset, FileSeekType_T aType);
+ STDMETHOD(SetACL)(IN_BSTR aACL);
+ STDMETHOD(Write)(ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten);
+ STDMETHOD(WriteAt)(LONG64 aOffset, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten);
+ /** @} */
+
+public:
+ /** @name Public internal methods.
+ * @{ */
+ static uint32_t getDispositionFromString(const Utf8Str &strDisposition);
+ static uint32_t getOpenModeFromString(const Utf8Str &strOpenMode);
+ /** @} */
+
+private:
+
+ struct Data
+ {
+ /** The associate session this file belongs to. */
+ GuestSession *mSession;
+ uint32_t mCreationMode;
+ uint32_t mDisposition;
+ Utf8Str mFileName;
+ int64_t mInitialSize;
+ uint32_t mOpenMode;
+ int64_t mOffset;
+ } mData;
+};
+
+#endif /* !____H_GUESTFILEIMPL */
+
diff --git a/src/VBox/Main/include/GuestFsObjInfoImpl.h b/src/VBox/Main/include/GuestFsObjInfoImpl.h
new file mode 100644
index 000000000..21ac02a8b
--- /dev/null
+++ b/src/VBox/Main/include/GuestFsObjInfoImpl.h
@@ -0,0 +1,85 @@
+
+/* $Id: GuestFsObjInfoImpl.h $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTFSOBJINFOIMPL
+#define ____H_GUESTFSOBJINFOIMPL
+
+#include "VirtualBoxBase.h"
+#include "GuestCtrlImplPrivate.h"
+
+/**
+ * TODO
+ */
+class ATL_NO_VTABLE GuestFsObjInfo :
+ public VirtualBoxBase,
+ VBOX_SCRIPTABLE_IMPL(IGuestFsObjInfo)
+{
+public:
+ /** @name COM and internal init/term/mapping cruft.
+ * @{ */
+ VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(GuestFsObjInfo, IGuestFsObjInfo)
+ DECLARE_NOT_AGGREGATABLE(GuestFsObjInfo)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+ BEGIN_COM_MAP(GuestFsObjInfo)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IGuestFsObjInfo)
+ COM_INTERFACE_ENTRY(IFsObjInfo)
+ END_COM_MAP()
+ DECLARE_EMPTY_CTOR_DTOR(GuestFsObjInfo)
+
+ int init(const GuestFsObjData &objData);
+ void uninit(void);
+ HRESULT FinalConstruct(void);
+ void FinalRelease(void);
+ /** @} */
+
+ /** @name IFsObjInfo interface.
+ * @{ */
+ STDMETHOD(COMGETTER(AccessTime))(LONG64 *aAccessTime);
+ STDMETHOD(COMGETTER(AllocatedSize))(LONG64 *aAllocatedSize);
+ STDMETHOD(COMGETTER(BirthTime))(LONG64 *aBirthTime);
+ STDMETHOD(COMGETTER(ChangeTime))(LONG64 *aChangeTime);
+ STDMETHOD(COMGETTER(DeviceNumber))(ULONG *aDeviceNumber);
+ STDMETHOD(COMGETTER(FileAttributes))(BSTR *aFileAttrs);
+ STDMETHOD(COMGETTER(GenerationId))(ULONG *aGenerationId);
+ STDMETHOD(COMGETTER(GID))(ULONG *aGID);
+ STDMETHOD(COMGETTER(GroupName))(BSTR *aGroupName);
+ STDMETHOD(COMGETTER(HardLinks))(ULONG *aHardLinks);
+ STDMETHOD(COMGETTER(ModificationTime))(LONG64 *aModificationTime);
+ STDMETHOD(COMGETTER(Name))(BSTR *aName);
+ STDMETHOD(COMGETTER(NodeId))(LONG64 *aNodeId);
+ STDMETHOD(COMGETTER(NodeIdDevice))(ULONG *aNodeIdDevice);
+ STDMETHOD(COMGETTER(ObjectSize))(LONG64 *aObjectSize);
+ STDMETHOD(COMGETTER(Type))(FsObjType_T *aType);
+ STDMETHOD(COMGETTER(UID))(ULONG *aUID);
+ STDMETHOD(COMGETTER(UserFlags))(ULONG *aUserFlags);
+ STDMETHOD(COMGETTER(UserName))(BSTR *aUserName);
+ STDMETHOD(COMGETTER(ACL))(BSTR *aACL);
+ /** @} */
+
+public:
+ /** @name Public internal methods.
+ * @{ */
+ /** @} */
+
+private:
+
+ GuestFsObjData mData;
+};
+
+#endif /* !____H_GUESTFSOBJINFOIMPL */
+
diff --git a/src/VBox/Main/include/GuestImpl.h b/src/VBox/Main/include/GuestImpl.h
index 5fea6a5a4..da6df5f62 100644
--- a/src/VBox/Main/include/GuestImpl.h
+++ b/src/VBox/Main/include/GuestImpl.h
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -21,14 +21,15 @@
#include <iprt/list.h>
#include <iprt/time.h>
#include <VBox/ostypes.h>
+#include <VBox/vmm/stam.h>
#include "AdditionsFacilityImpl.h"
#include "GuestCtrlImplPrivate.h"
+#include "GuestSessionImpl.h"
#include "HGCM.h"
-#ifdef VBOX_WITH_GUEST_CONTROL
-# include <iprt/fs.h>
-# include <VBox/HostServices/GuestControlSvc.h>
-using namespace guestControl;
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+class GuestDnD;
#endif
typedef enum
@@ -67,58 +68,60 @@ public:
DECLARE_EMPTY_CTOR_DTOR (Guest)
- HRESULT FinalConstruct();
- void FinalRelease();
+ HRESULT FinalConstruct(void);
+ void FinalRelease(void);
- // Public initializer/uninitializer for internal purposes only
+ // Public initializer/uninitializer for internal purposes only.
HRESULT init (Console *aParent);
void uninit();
- // IGuest properties
+ // IGuest properties.
STDMETHOD(COMGETTER(OSTypeId)) (BSTR *aOSTypeId);
STDMETHOD(COMGETTER(AdditionsRunLevel)) (AdditionsRunLevelType_T *aRunLevel);
STDMETHOD(COMGETTER(AdditionsVersion))(BSTR *a_pbstrAdditionsVersion);
- STDMETHOD(COMGETTER(Facilities)) (ComSafeArrayOut(IAdditionsFacility*, aFacilities));
+ STDMETHOD(COMGETTER(AdditionsRevision))(ULONG *a_puAdditionsRevision);
+ STDMETHOD(COMGETTER(Facilities)) (ComSafeArrayOut(IAdditionsFacility *, aFacilities));
+ STDMETHOD(COMGETTER(Sessions)) (ComSafeArrayOut(IGuestSession *, aSessions));
STDMETHOD(COMGETTER(MemoryBalloonSize)) (ULONG *aMemoryBalloonSize);
STDMETHOD(COMSETTER(MemoryBalloonSize)) (ULONG aMemoryBalloonSize);
STDMETHOD(COMGETTER(StatisticsUpdateInterval)) (ULONG *aUpdateInterval);
STDMETHOD(COMSETTER(StatisticsUpdateInterval)) (ULONG aUpdateInterval);
-
- // IGuest methods
+ // IGuest methods.
STDMETHOD(GetFacilityStatus)(AdditionsFacilityType_T aType, LONG64 *aTimestamp, AdditionsFacilityStatus_T *aStatus);
STDMETHOD(GetAdditionsStatus)(AdditionsRunLevelType_T aLevel, BOOL *aActive);
STDMETHOD(SetCredentials)(IN_BSTR aUsername, IN_BSTR aPassword,
IN_BSTR aDomain, BOOL aAllowInteractiveLogon);
- // Process execution
- STDMETHOD(ExecuteProcess)(IN_BSTR aCommand, ULONG aFlags,
- ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress);
- STDMETHOD(GetProcessOutput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, LONG64 aSize, ComSafeArrayOut(BYTE, aData));
- STDMETHOD(SetProcessInput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, ComSafeArrayIn(BYTE, aData), ULONG *aBytesWritten);
- STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ExecuteProcessStatus_T *aStatus);
- // File copying
- STDMETHOD(CopyFromGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUsername, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress);
- STDMETHOD(CopyToGuest)(IN_BSTR aSource, IN_BSTR aDest, IN_BSTR aUsername, IN_BSTR aPassword, ULONG aFlags, IProgress **aProgress);
- // Directory handling
- STDMETHOD(DirectoryClose)(ULONG aHandle);
- STDMETHOD(DirectoryCreate)(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, ULONG aMode, ULONG aFlags);
-#if 0
- STDMETHOD(DirectoryExists)(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists);
-#endif
- STDMETHOD(DirectoryOpen)(IN_BSTR aDirectory, IN_BSTR aFilter,
- ULONG aFlags, IN_BSTR aUsername, IN_BSTR aPassword, ULONG *aHandle);
- STDMETHOD(DirectoryRead)(ULONG aHandle, IGuestDirEntry **aDirEntry);
- // File handling
- STDMETHOD(FileExists)(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists);
- STDMETHOD(FileQuerySize)(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize);
+ // Drag'n drop support.
+ STDMETHOD(DragHGEnter)(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction);
+ STDMETHOD(DragHGMove)(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction);
+ STDMETHOD(DragHGLeave)(ULONG uScreenId);
+ STDMETHOD(DragHGDrop)(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction);
+ STDMETHOD(DragHGPutData)(ULONG uScreenId, IN_BSTR strFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress);
+ STDMETHOD(DragGHPending)(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction);
+ STDMETHOD(DragGHDropped)(IN_BSTR strFormat, DragAndDropAction_T action, IProgress **ppProgress);
+ STDMETHOD(DragGHGetData)(ComSafeArrayOut(BYTE, data));
// Misc stuff
STDMETHOD(InternalGetStatistics)(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle,
ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared, ULONG *aMemCache,
ULONG *aPageTotal, ULONG *aMemAllocTotal, ULONG *aMemFreeTotal, ULONG *aMemBalloonTotal, ULONG *aMemSharedTotal);
- STDMETHOD(UpdateGuestAdditions)(IN_BSTR aSource, ULONG aFlags, IProgress **aProgress);
+ STDMETHOD(UpdateGuestAdditions)(IN_BSTR aSource, ComSafeArrayIn(AdditionsUpdateFlag_T, aFlags), IProgress **aProgress);
+ STDMETHOD(CreateSession)(IN_BSTR aUser, IN_BSTR aPassword, IN_BSTR aDomain, IN_BSTR aSessionName, IGuestSession **aGuestSession);
+ STDMETHOD(FindSession)(IN_BSTR aSessionName, ComSafeArrayOut(IGuestSession *, aSessions));
- // Public methods that are not in IDL (only called internally).
+public:
+ /** @name Static internal methods.
+ * @{ */
+#ifdef VBOX_WITH_GUEST_CONTROL
+ /** Static callback for handling guest control notifications. */
+ static DECLCALLBACK(int) notifyCtrlDispatcher(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
+ static void staticUpdateStats(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick);
+#endif
+ /** @} */
+
+public:
+ /** @name Public internal methods.
+ * @{ */
+ void enableVMMStatistics(BOOL aEnable) { mCollectVMMStats = aEnable; };
void setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType);
void setAdditionsInfo2(uint32_t a_uFullVersion, const char *a_pszName, uint32_t a_uRevision, uint32_t a_fFeatures);
bool facilityIsActive(VBoxGuestFacilityType enmFacility);
@@ -132,154 +135,32 @@ public:
{
return setErrorInternal(aResultCode, getStaticClassIID(), getStaticComponentName(), aText, false, true);
}
-
-# ifdef VBOX_WITH_GUEST_CONTROL
- // Internal guest directory functions
- int directoryCreateHandle(ULONG *puHandle, ULONG uPID, IN_BSTR aDirectory, IN_BSTR aFilter, ULONG uFlags);
- HRESULT directoryCreateInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG aMode, ULONG aFlags, int *pRC);
- void directoryDestroyHandle(uint32_t uHandle);
- HRESULT directoryExistsInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists);
- uint32_t directoryGetPID(uint32_t uHandle);
- int directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock);
- bool directoryHandleExists(uint32_t uHandle);
- HRESULT directoryOpenInternal(IN_BSTR aDirectory, IN_BSTR aFilter,
- ULONG aFlags,
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG *aHandle, int *pRC);
- HRESULT directoryQueryInfoInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs, int *pRC);
- // Internal guest execution functions
- HRESULT executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription,
- ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG uFlagsToAdd,
- GuestCtrlStreamObjects *pObjStdOut, GuestCtrlStreamObjects *pObjStdErr,
- IProgress **aProgress, ULONG *aPID);
- HRESULT executeProcessInternal(IN_BSTR aCommand, ULONG aFlags,
- ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC);
- HRESULT getProcessOutputInternal(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS,
- LONG64 aSize, ComSafeArrayOut(BYTE, aData), int *pRC);
- HRESULT executeSetResult(const char *pszCommand, const char *pszUser, ULONG ulTimeout, PCALLBACKDATAEXECSTATUS pExecStatus, ULONG *puPID);
- int executeStreamQueryFsObjInfo(IN_BSTR aObjName,GuestProcessStreamBlock &streamBlock, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttribs);
- int executeStreamDrain(ULONG aPID, ULONG ulFlags, GuestProcessStream *pStream);
- int executeStreamGetNextBlock(ULONG ulPID, ULONG ulFlags, GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock);
- int executeStreamParseNextBlock(ULONG ulPID, ULONG ulFlags, GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock);
- HRESULT executeStreamParse(ULONG uPID, ULONG ulFlags, GuestCtrlStreamObjects &streamObjects);
- HRESULT executeWaitForExit(ULONG uPID, ComPtr<IProgress> pProgress, ULONG uTimeoutMS);
- // Internal guest file functions
- HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists);
- HRESULT fileQueryInfoInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs, int *pRC);
- HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize);
-
- // Guest control dispatcher.
- /** Static callback for handling guest notifications. */
- static DECLCALLBACK(int) notifyCtrlDispatcher(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
-
- // Internal tasks.
- //extern struct GuestTask;
- HRESULT taskCopyFileToGuest(GuestTask *aTask);
- HRESULT taskCopyFileFromGuest(GuestTask *aTask);
- HRESULT taskUpdateGuestAdditions(GuestTask *aTask);
-# endif
- void enableVMMStatistics(BOOL aEnable) { mCollectVMMStats = aEnable; };
-
-private:
-
#ifdef VBOX_WITH_GUEST_CONTROL
- // Internal guest callback representation.
- typedef struct VBOXGUESTCTRL_CALLBACK
- {
- eVBoxGuestCtrlCallbackType mType;
- /** Pointer to user-supplied data. */
- void *pvData;
- /** Size of user-supplied data. */
- uint32_t cbData;
- /** The host PID. Needed for translating to
- * a guest PID. */
- uint32_t uHostPID;
- /** Pointer to user-supplied IProgress. */
- ComObjPtr<Progress> pProgress;
- } VBOXGUESTCTRL_CALLBACK, *PVBOXGUESTCTRL_CALLBACK;
- typedef std::map< uint32_t, VBOXGUESTCTRL_CALLBACK > CallbackMap;
- typedef std::map< uint32_t, VBOXGUESTCTRL_CALLBACK >::iterator CallbackMapIter;
- typedef std::map< uint32_t, VBOXGUESTCTRL_CALLBACK >::const_iterator CallbackMapIterConst;
-
- int callbackAdd(const PVBOXGUESTCTRL_CALLBACK pCallbackData, uint32_t *puContextID);
- int callbackAssignHostPID(uint32_t uContextID, uint32_t uHostPID);
- void callbackDestroy(uint32_t uContextID);
- void callbackRemove(uint32_t uContextID);
- bool callbackExists(uint32_t uContextID);
- void callbackFreeUserData(void *pvData);
- uint32_t callbackGetHostPID(uint32_t uContextID);
- int callbackGetUserData(uint32_t uContextID, eVBoxGuestCtrlCallbackType *pEnmType, void **ppvData, size_t *pcbData);
- void* callbackGetUserDataMutableRaw(uint32_t uContextID, size_t *pcbData);
- int callbackInit(PVBOXGUESTCTRL_CALLBACK pCallback, eVBoxGuestCtrlCallbackType enmType, ComPtr<Progress> pProgress);
- bool callbackIsCanceled(uint32_t uContextID);
- bool callbackIsComplete(uint32_t uContextID);
- int callbackMoveForward(uint32_t uContextID, const char *pszMessage);
- int callbackNotifyEx(uint32_t uContextID, int iRC, const char *pszMessage);
- int callbackNotifyComplete(uint32_t uContextID);
- int callbackNotifyAllForPID(uint32_t uGuestPID, int iRC, const char *pszMessage);
- int callbackWaitForCompletion(uint32_t uContextID, LONG lStage, LONG lTimeout);
-
- int notifyCtrlClientDisconnected(uint32_t u32Function, PCALLBACKDATACLIENTDISCONNECTED pData);
- int notifyCtrlExecStatus(uint32_t u32Function, PCALLBACKDATAEXECSTATUS pData);
- int notifyCtrlExecOut(uint32_t u32Function, PCALLBACKDATAEXECOUT pData);
- int notifyCtrlExecInStatus(uint32_t u32Function, PCALLBACKDATAEXECINSTATUS pData);
-
- // Internal guest process representation.
- typedef struct VBOXGUESTCTRL_PROCESS
- {
- /** The guest PID -- needed for controlling the actual guest
- * process which has its own PID (generated by the guest OS). */
- uint32_t mGuestPID;
- /** The last reported process status. */
- ExecuteProcessStatus_T mStatus;
- /** The process execution flags. */
- uint32_t mFlags;
- /** The process' exit code. */
- uint32_t mExitCode;
- } VBOXGUESTCTRL_PROCESS, *PVBOXGUESTCTRL_PROCESS;
- typedef std::map< uint32_t, VBOXGUESTCTRL_PROCESS > GuestProcessMap;
- typedef std::map< uint32_t, VBOXGUESTCTRL_PROCESS >::iterator GuestProcessMapIter;
- typedef std::map< uint32_t, VBOXGUESTCTRL_PROCESS >::const_iterator GuestProcessMapIterConst;
-
- uint32_t processGetGuestPID(uint32_t uHostPID);
- int processGetStatus(uint32_t uHostPID, PVBOXGUESTCTRL_PROCESS pProcess, bool fRemove);
- int processSetStatus(uint32_t uHostPID, uint32_t uGuestPID,
- ExecuteProcessStatus_T enmStatus, uint32_t uExitCode, uint32_t uFlags);
-
- // Internal guest directory representation.
- typedef struct VBOXGUESTCTRL_DIRECTORY
- {
- Bstr mDirectory;
- Bstr mFilter;
- ULONG mFlags;
- /** Associated host PID of started vbox_ls tool. */
- ULONG mPID;
- GuestProcessStream mStream;
- } VBOXGUESTCTRL_DIRECTORY, *PVBOXGUESTCTRL_DIRECTORY;
- typedef std::map< uint32_t, VBOXGUESTCTRL_DIRECTORY > GuestDirectoryMap;
- typedef std::map< uint32_t, VBOXGUESTCTRL_DIRECTORY >::iterator GuestDirectoryMapIter;
- typedef std::map< uint32_t, VBOXGUESTCTRL_DIRECTORY >::const_iterator GuestDirectoryMapIterConst;
-
- // Utility functions.
- int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv);
+ int dispatchToSession(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData);
+ uint32_t getAdditionsVersion(void) { return mData.mAdditionsVersionFull; }
+ Console *getConsole(void) { return mParent; }
+ int sessionRemove(GuestSession *pSession);
+ int sessionCreate(const Utf8Str &strUser, const Utf8Str &strPassword, const Utf8Str &strDomain,
+ const Utf8Str &strSessionName, ComObjPtr<GuestSession> &pGuestSession);
+ inline bool sessionExists(uint32_t uSessionID);
+#endif
+ /** @} */
- /*
- * Handler for guest execution control notifications.
- */
- HRESULT setErrorCompletion(int rc);
- HRESULT setErrorFromProgress(ComPtr<IProgress> pProgress);
- HRESULT setErrorHGCM(int rc);
-# endif
+private:
+ /** @name Private internal methods.
+ * @{ */
+ void updateStats(uint64_t iTick);
+ static int staticEnumStatsCallback(const char *pszName, STAMTYPE enmType, void *pvSample, STAMUNIT enmUnit,
+ STAMVISIBILITY enmVisiblity, const char *pszDesc, void *pvUser);
+ /** @} */
typedef std::map< AdditionsFacilityType_T, ComObjPtr<AdditionsFacility> > FacilityMap;
typedef std::map< AdditionsFacilityType_T, ComObjPtr<AdditionsFacility> >::iterator FacilityMapIter;
typedef std::map< AdditionsFacilityType_T, ComObjPtr<AdditionsFacility> >::const_iterator FacilityMapIterConst;
+ /** Map for keeping the guest sessions. The primary key marks the guest session ID. */
+ typedef std::map <uint32_t, ComObjPtr<GuestSession> > GuestSessions;
+
struct Data
{
Data() : mAdditionsRunLevel(AdditionsRunLevelType_None)
@@ -294,37 +175,38 @@ private:
uint32_t mAdditionsRevision;
uint32_t mAdditionsFeatures;
Bstr mInterfaceVersion;
+ GuestSessions mGuestSessions;
+ uint32_t mNextSessionID;
};
- ULONG mMemoryBalloonSize;
- ULONG mStatUpdateInterval;
- ULONG mCurrentGuestStat[GUESTSTATTYPE_MAX];
- ULONG mGuestValidStats;
- BOOL mCollectVMMStats;
- BOOL mfPageFusionEnabled;
+ ULONG mMemoryBalloonSize;
+ ULONG mStatUpdateInterval;
+ uint64_t mNetStatRx;
+ uint64_t mNetStatTx;
+ uint64_t mNetStatLastTs;
+ ULONG mCurrentGuestStat[GUESTSTATTYPE_MAX];
+ ULONG mVmValidStats;
+ BOOL mCollectVMMStats;
+ BOOL mfPageFusionEnabled;
Console *mParent;
Data mData;
-# ifdef VBOX_WITH_GUEST_CONTROL
+#ifdef VBOX_WITH_GUEST_CONTROL
/** General extension callback for guest control. */
HGCMSVCEXTHANDLE mhExtCtrl;
- /** Next upcoming context ID. */
- volatile uint32_t mNextContextID;
- /** Next upcoming host PID */
- volatile uint32_t mNextHostPID;
- /** Next upcoming directory handle ID. */
- volatile uint32_t mNextDirectoryID;
- CallbackMap mCallbackMap;
- GuestDirectoryMap mGuestDirectoryMap;
- GuestProcessMap mGuestProcessMap;
-# endif
- static void staticUpdateStats(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick);
- void updateStats(uint64_t iTick);
+#endif
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ GuestDnD *m_pGuestDnD;
+ friend class GuestDnD;
+ friend class GuestDnDPrivate;
+#endif
+
RTTIMERLR mStatTimer;
uint32_t mMagic;
};
#define GUEST_MAGIC 0xCEED2006u
#endif // ____H_GUESTIMPL
-/* vi: set tabstop=4 shiftwidth=4 expandtab: */
+
diff --git a/src/VBox/Main/include/GuestOSTypeImpl.h b/src/VBox/Main/include/GuestOSTypeImpl.h
index f1c196a44..72ad31705 100644
--- a/src/VBox/Main/include/GuestOSTypeImpl.h
+++ b/src/VBox/Main/include/GuestOSTypeImpl.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -57,20 +57,24 @@ public:
STDMETHOD(COMGETTER(RecommendedVirtEx))(BOOL *aRecommendedVirtEx);
STDMETHOD(COMGETTER(RecommendedRAM))(ULONG *aRAMSize);
STDMETHOD(COMGETTER(RecommendedVRAM))(ULONG *aVRAMSize);
+ STDMETHOD(COMGETTER(Recommended2DVideoAcceleration))(BOOL *aRecommended2DVideoAcceleration);
+ STDMETHOD(COMGETTER(Recommended3DAcceleration))(BOOL *aRecommended3DAcceleration);
STDMETHOD(COMGETTER(RecommendedHDD))(LONG64 *aHDDSize);
STDMETHOD(COMGETTER(AdapterType))(NetworkAdapterType_T *aNetworkAdapterType);
STDMETHOD(COMGETTER(RecommendedFirmware))(FirmwareType_T *aFirmwareType);
- STDMETHOD(COMGETTER(RecommendedDvdStorageBus))(StorageBus_T *aStorageBusType);
- STDMETHOD(COMGETTER(RecommendedDvdStorageController))(StorageControllerType_T *aStorageControllerType);
- STDMETHOD(COMGETTER(RecommendedHdStorageBus))(StorageBus_T *aStorageBusType);
- STDMETHOD(COMGETTER(RecommendedHdStorageController))(StorageControllerType_T *aStorageControllerType);
- STDMETHOD(COMGETTER(RecommendedPae))(BOOL *aRecommendedExtHw);
- STDMETHOD(COMGETTER(RecommendedUsbHid))(BOOL *aRecommendedUsbHid);
- STDMETHOD(COMGETTER(RecommendedHpet))(BOOL *aRecommendedHpet);
- STDMETHOD(COMGETTER(RecommendedUsbTablet))(BOOL *aRecommendedUsbTablet);
- STDMETHOD(COMGETTER(RecommendedRtcUseUtc))(BOOL *aRecommendedRtcUseUtc);
- STDMETHOD(COMGETTER(RecommendedChipset)) (ChipsetType_T *aChipsetType);
- STDMETHOD(COMGETTER(RecommendedAudioController)) (AudioControllerType_T *aAudioController);
+ STDMETHOD(COMGETTER(RecommendedDVDStorageBus))(StorageBus_T *aStorageBusType);
+ STDMETHOD(COMGETTER(RecommendedDVDStorageController))(StorageControllerType_T *aStorageControllerType);
+ STDMETHOD(COMGETTER(RecommendedHDStorageBus))(StorageBus_T *aStorageBusType);
+ STDMETHOD(COMGETTER(RecommendedHDStorageController))(StorageControllerType_T *aStorageControllerType);
+ STDMETHOD(COMGETTER(RecommendedPAE))(BOOL *aRecommendedExtHw);
+ STDMETHOD(COMGETTER(RecommendedUSBHID))(BOOL *aRecommendedUSBHID);
+ STDMETHOD(COMGETTER(RecommendedHPET))(BOOL *aRecommendedHPET);
+ STDMETHOD(COMGETTER(RecommendedUSBTablet))(BOOL *aRecommendedUSBTablet);
+ STDMETHOD(COMGETTER(RecommendedRTCUseUTC))(BOOL *aRecommendedRTCUseUTC);
+ STDMETHOD(COMGETTER(RecommendedChipset))(ChipsetType_T *aChipsetType);
+ STDMETHOD(COMGETTER(RecommendedAudioController))(AudioControllerType_T *aAudioController);
+ STDMETHOD(COMGETTER(RecommendedFloppy))(BOOL *aRecommendedFloppy);
+ STDMETHOD(COMGETTER(RecommendedUSB))(BOOL *aRecommendedUSB);
// public methods only for internal purposes
const Bstr &id() const { return mID; }
@@ -95,10 +99,10 @@ private:
const uint32_t mMonitorCount;
const NetworkAdapterType_T mNetworkAdapterType;
const uint32_t mNumSerialEnabled;
- const StorageControllerType_T mDvdStorageControllerType;
- const StorageBus_T mDvdStorageBusType;
- const StorageControllerType_T mHdStorageControllerType;
- const StorageBus_T mHdStorageBusType;
+ const StorageControllerType_T mDVDStorageControllerType;
+ const StorageBus_T mDVDStorageBusType;
+ const StorageControllerType_T mHDStorageControllerType;
+ const StorageBus_T mHDStorageBusType;
const ChipsetType_T mChipsetType;
const AudioControllerType_T mAudioControllerType;
};
diff --git a/src/VBox/Main/include/GuestProcessImpl.h b/src/VBox/Main/include/GuestProcessImpl.h
new file mode 100644
index 000000000..8b83eb2ec
--- /dev/null
+++ b/src/VBox/Main/include/GuestProcessImpl.h
@@ -0,0 +1,195 @@
+
+/* $Id: GuestProcessImpl.h $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTPROCESSIMPL
+#define ____H_GUESTPROCESSIMPL
+
+#include "VirtualBoxBase.h"
+#include "GuestCtrlImplPrivate.h"
+
+class Console;
+class GuestSession;
+
+/**
+ * TODO
+ */
+class ATL_NO_VTABLE GuestProcess :
+ public VirtualBoxBase,
+ VBOX_SCRIPTABLE_IMPL(IGuestProcess)
+{
+public:
+ /** @name COM and internal init/term/mapping cruft.
+ * @{ */
+ VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(GuestProcess, IGuestProcess)
+ DECLARE_NOT_AGGREGATABLE(GuestProcess)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+ BEGIN_COM_MAP(GuestProcess)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IGuestProcess)
+ COM_INTERFACE_ENTRY(IProcess)
+ END_COM_MAP()
+ DECLARE_EMPTY_CTOR_DTOR(GuestProcess)
+
+ int init(Console *aConsole, GuestSession *aSession, ULONG aProcessID, const GuestProcessStartupInfo &aProcInfo);
+ void uninit(void);
+ HRESULT FinalConstruct(void);
+ void FinalRelease(void);
+ /** @} */
+
+ /** @name IProcess interface.
+ * @{ */
+ STDMETHOD(COMGETTER(Arguments))(ComSafeArrayOut(BSTR, aArguments));
+ STDMETHOD(COMGETTER(Environment))(ComSafeArrayOut(BSTR, aEnvironment));
+ STDMETHOD(COMGETTER(ExecutablePath))(BSTR *aExecutablePath);
+ STDMETHOD(COMGETTER(ExitCode))(LONG *aExitCode);
+ STDMETHOD(COMGETTER(Name))(BSTR *aName);
+ STDMETHOD(COMGETTER(PID))(ULONG *aPID);
+ STDMETHOD(COMGETTER(Status))(ProcessStatus_T *aStatus);
+
+ STDMETHOD(Read)(ULONG aHandle, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData));
+ STDMETHOD(Terminate)(void);
+ STDMETHOD(WaitFor)(ULONG aWaitFlags, ULONG aTimeoutMS, ProcessWaitResult_T *aReason);
+ STDMETHOD(WaitForArray)(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason);
+ STDMETHOD(Write)(ULONG aHandle, ULONG aFlags, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten);
+ STDMETHOD(WriteArray)(ULONG aHandle, ComSafeArrayIn(ProcessInputFlag_T, aFlags), ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten);
+ /** @} */
+
+public:
+ /** @name Public internal methods.
+ * @{ */
+ int callbackDispatcher(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData);
+ inline bool callbackExists(uint32_t uContextID);
+ inline int checkPID(uint32_t uPID);
+ static Utf8Str guestErrorToString(int guestRc);
+ bool isReady(void);
+ ULONG getProcessID(void) { return mData.mProcessID; }
+ int readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS, void *pvData, size_t cbData, size_t *pcbRead, int *pGuestRc);
+ static HRESULT setErrorExternal(VirtualBoxBase *pInterface, int guestRc);
+ int startProcess(int *pGuestRc);
+ int startProcessAsync(void);
+ int terminateProcess(void);
+ int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc);
+ int writeData(uint32_t uHandle, uint32_t uFlags, void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten, int *pGuestRc);
+ /** @} */
+
+protected:
+ /** @name Protected internal methods.
+ * @{ */
+ inline int callbackAdd(GuestCtrlCallback *pCallback, uint32_t *puContextID);
+ inline int callbackRemove(uint32_t uContextID);
+ inline bool isAlive(void);
+ int onGuestDisconnected(GuestCtrlCallback *pCallback, PCALLBACKDATACLIENTDISCONNECTED pData);
+ int onProcessInputStatus(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECINSTATUS pData);
+ int onProcessNotifyIO(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData);
+ int onProcessStatusChange(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData);
+ int onProcessOutput(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECOUT pData);
+ int prepareExecuteEnv(const char *pszEnv, void **ppvList, ULONG *pcbList, ULONG *pcEnvVars);
+ int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
+ int setProcessStatus(ProcessStatus_T procStatus, int procRc);
+ int signalWaiters(ProcessWaitResult_T enmWaitResult, int rc = VINF_SUCCESS);
+ static DECLCALLBACK(int) startProcessThread(RTTHREAD Thread, void *pvUser);
+ /** @} */
+
+private:
+
+ struct Data
+ {
+ /** Pointer to parent session. Per definition
+ * this objects *always* lives shorter than the
+ * parent. */
+ GuestSession *mParent;
+ /** Pointer to the console object. Needed
+ * for HGCM (VMMDev) communication. */
+ Console *mConsole;
+ /** All related callbacks to this process. */
+ GuestCtrlCallbacks mCallbacks;
+ /** The process start information. */
+ GuestProcessStartupInfo mProcess;
+ /** Exit code if process has been terminated. */
+ LONG mExitCode;
+ /** PID reported from the guest. */
+ ULONG mPID;
+ /** Internal, host-side process ID. */
+ ULONG mProcessID;
+ /** The current process status. */
+ ProcessStatus_T mStatus;
+ int mRC;
+ /** The next upcoming context ID. */
+ ULONG mNextContextID;
+ /** The mutex for protecting the waiter(s). */
+ RTSEMMUTEX mWaitMutex;
+ /** How many waiters? At the moment there can only
+ * be one. */
+ uint32_t mWaitCount;
+ /** The actual process event for doing the waits.
+ * At the moment we only support one wait a time. */
+ GuestProcessWaitEvent *mWaitEvent;
+ } mData;
+};
+
+/**
+ * Guest process tool flags.
+ */
+/** No flags specified. */
+#define GUESTPROCESSTOOL_FLAG_NONE 0
+/** Run until next stream block from stdout has been
+ * read in completely, then return.
+ */
+#define GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK RT_BIT(0)
+
+/**
+ * Internal class for handling a VBoxService tool ("vbox_ls", vbox_stat", ...).
+ */
+class GuestProcessTool
+{
+public:
+
+ GuestProcessTool(void);
+
+ virtual ~GuestProcessTool(void);
+
+public:
+
+ int Init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pGuestRc);
+
+ GuestProcessStream &GetStdOut(void) { return mStdOut; }
+
+ GuestProcessStream &GetStdErr(void) { return mStdErr; }
+
+ int Wait(uint32_t fFlags, int *pGuestRc);
+
+ int WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc);
+
+ int GetCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock);
+
+ bool IsRunning(void);
+
+ int TerminatedOk(LONG *pExitCode);
+
+ void Terminate(void);
+
+protected:
+
+ GuestSession *pSession;
+ ComObjPtr<GuestProcess> pProcess;
+ GuestProcessStartupInfo mStartupInfo;
+ GuestProcessStream mStdOut;
+ GuestProcessStream mStdErr;
+};
+
+#endif /* !____H_GUESTPROCESSIMPL */
+
diff --git a/src/VBox/Main/include/GuestSessionImpl.h b/src/VBox/Main/include/GuestSessionImpl.h
new file mode 100644
index 000000000..fc2bc307e
--- /dev/null
+++ b/src/VBox/Main/include/GuestSessionImpl.h
@@ -0,0 +1,362 @@
+
+/* $Id: GuestSessionImpl.h $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTSESSIONIMPL
+#define ____H_GUESTSESSIONIMPL
+
+#include "VirtualBoxBase.h"
+
+#include "GuestCtrlImplPrivate.h"
+#include "GuestProcessImpl.h"
+#include "GuestDirectoryImpl.h"
+#include "GuestFileImpl.h"
+#include "GuestFsObjInfoImpl.h"
+
+#include <iprt/isofs.h> /* For UpdateAdditions. */
+
+class Guest;
+
+/**
+ * Abstract base class for a lenghtly per-session operation which
+ * runs in a Main worker thread.
+ */
+class GuestSessionTask
+{
+public:
+
+ GuestSessionTask(GuestSession *pSession);
+
+ virtual ~GuestSessionTask(void);
+
+public:
+
+ virtual int Run(void) = 0;
+ virtual int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress) = 0;
+
+protected:
+
+ int getGuestProperty(const ComObjPtr<Guest> &pGuest,
+ const Utf8Str &strPath, Utf8Str &strValue);
+ int setProgress(ULONG uPercent);
+ int setProgressSuccess(void);
+ HRESULT setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg);
+
+protected:
+
+ Utf8Str mDesc;
+ GuestSession *mSession;
+ /** Progress object for getting updated when running
+ * asynchronously. Optional. */
+ ComObjPtr<Progress> mProgress;
+};
+
+/**
+ * Task for copying files from host to the guest.
+ */
+class SessionTaskCopyTo : public GuestSessionTask
+{
+public:
+
+ SessionTaskCopyTo(GuestSession *pSession,
+ const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags);
+
+ SessionTaskCopyTo(GuestSession *pSession,
+ PRTFILE pSourceFile, size_t cbSourceOffset, uint64_t cbSourceSize,
+ const Utf8Str &strDest, uint32_t uFlags);
+
+ virtual ~SessionTaskCopyTo(void);
+
+public:
+
+ int Run(void);
+ int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
+ static int taskThread(RTTHREAD Thread, void *pvUser);
+
+protected:
+
+ Utf8Str mSource;
+ PRTFILE mSourceFile;
+ size_t mSourceOffset;
+ uint64_t mSourceSize;
+ Utf8Str mDest;
+ uint32_t mCopyFileFlags;
+};
+
+/**
+ * Task for copying files from guest to the host.
+ */
+class SessionTaskCopyFrom : public GuestSessionTask
+{
+public:
+
+ SessionTaskCopyFrom(GuestSession *pSession,
+ const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags);
+
+ virtual ~SessionTaskCopyFrom(void);
+
+public:
+
+ int Run(void);
+ int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
+ static int taskThread(RTTHREAD Thread, void *pvUser);
+
+protected:
+
+ Utf8Str mSource;
+ Utf8Str mDest;
+ uint32_t mFlags;
+};
+
+/**
+ * Task for automatically updating the Guest Additions on the guest.
+ */
+class SessionTaskUpdateAdditions : public GuestSessionTask
+{
+public:
+
+ SessionTaskUpdateAdditions(GuestSession *pSession,
+ const Utf8Str &strSource, uint32_t uFlags);
+
+ virtual ~SessionTaskUpdateAdditions(void);
+
+public:
+
+ int Run(void);
+ int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
+ static int taskThread(RTTHREAD Thread, void *pvUser);
+
+protected:
+
+ /**
+ * Suported OS types for automatic updating.
+ */
+ enum eOSType
+ {
+ eOSType_Unknown = 0,
+ eOSType_Windows = 1,
+ eOSType_Linux = 2,
+ eOSType_Solaris = 3
+ };
+
+ /**
+ * Structure representing a file to
+ * get off the .ISO, copied to the guest.
+ */
+ struct InstallerFile
+ {
+ InstallerFile(const Utf8Str &aSource,
+ const Utf8Str &aDest,
+ uint32_t aFlags = 0)
+ : strSource(aSource),
+ strDest(aDest),
+ fFlags(aFlags) { }
+
+ InstallerFile(const Utf8Str &aSource,
+ const Utf8Str &aDest,
+ uint32_t aFlags,
+ GuestProcessStartupInfo startupInfo)
+ : strSource(aSource),
+ strDest(aDest),
+ fFlags(aFlags),
+ mProcInfo(startupInfo)
+ {
+ mProcInfo.mCommand = strDest;
+ if (mProcInfo.mName.isEmpty())
+ mProcInfo.mName = strDest;
+ }
+
+ /** Source file on .ISO. */
+ Utf8Str strSource;
+ /** Destination file on the guest. */
+ Utf8Str strDest;
+ /** File flags. */
+ uint32_t fFlags;
+ /** Optional arguments if this file needs to be
+ * executed. */
+ GuestProcessStartupInfo mProcInfo;
+ };
+
+ int copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,
+ Utf8Str const &strFileSource, const Utf8Str &strFileDest,
+ bool fOptional, uint32_t *pcbSize);
+ int runFileOnGuest(GuestSession *pSession, GuestProcessStartupInfo &procInfo);
+
+ /** Files to handle. */
+ std::vector<InstallerFile> mFiles;
+ /** The (optionally) specified Guest Additions .ISO on the host
+ * which will be used for the updating process. */
+ Utf8Str mSource;
+ /** Update flags. */
+ uint32_t mFlags;
+};
+
+/**
+ * Guest session implementation.
+ */
+class ATL_NO_VTABLE GuestSession :
+ public VirtualBoxBase,
+ VBOX_SCRIPTABLE_IMPL(IGuestSession)
+{
+public:
+ /** @name COM and internal init/term/mapping cruft.
+ * @{ */
+ VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(GuestSession, IGuestSession)
+ DECLARE_NOT_AGGREGATABLE(GuestSession)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+ BEGIN_COM_MAP(GuestSession)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IGuestSession)
+ END_COM_MAP()
+ DECLARE_EMPTY_CTOR_DTOR(GuestSession)
+
+ int init(Guest *aGuest, ULONG aSessionID, Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName);
+ void uninit(void);
+ HRESULT FinalConstruct(void);
+ void FinalRelease(void);
+ /** @} */
+
+ /** @name IGuestSession properties.
+ * @{ */
+ STDMETHOD(COMGETTER(User))(BSTR *aName);
+ STDMETHOD(COMGETTER(Domain))(BSTR *aDomain);
+ STDMETHOD(COMGETTER(Name))(BSTR *aName);
+ STDMETHOD(COMGETTER(Id))(ULONG *aId);
+ STDMETHOD(COMGETTER(Timeout))(ULONG *aTimeout);
+ STDMETHOD(COMSETTER(Timeout))(ULONG aTimeout);
+ STDMETHOD(COMGETTER(Environment))(ComSafeArrayOut(BSTR, aEnvironment));
+ STDMETHOD(COMSETTER(Environment))(ComSafeArrayIn(IN_BSTR, aEnvironment));
+ STDMETHOD(COMGETTER(Processes))(ComSafeArrayOut(IGuestProcess *, aProcesses));
+ STDMETHOD(COMGETTER(Directories))(ComSafeArrayOut(IGuestDirectory *, aDirectories));
+ STDMETHOD(COMGETTER(Files))(ComSafeArrayOut(IGuestFile *, aFiles));
+ /** @} */
+
+ /** @name IGuestSession methods.
+ * @{ */
+ STDMETHOD(Close)(void);
+ STDMETHOD(CopyFrom)(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress);
+ STDMETHOD(CopyTo)(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress);
+ STDMETHOD(DirectoryCreate)(IN_BSTR aPath, ULONG aMode, ComSafeArrayIn(DirectoryCreateFlag_T, aFlags));
+ STDMETHOD(DirectoryCreateTemp)(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, BSTR *aDirectory);
+ STDMETHOD(DirectoryExists)(IN_BSTR aPath, BOOL *aExists);
+ STDMETHOD(DirectoryOpen)(IN_BSTR aPath, IN_BSTR aFilter, ComSafeArrayIn(DirectoryOpenFlag_T, aFlags), IGuestDirectory **aDirectory);
+ STDMETHOD(DirectoryQueryInfo)(IN_BSTR aPath, IGuestFsObjInfo **aInfo);
+ STDMETHOD(DirectoryRemove)(IN_BSTR aPath);
+ STDMETHOD(DirectoryRemoveRecursive)(IN_BSTR aPath, ComSafeArrayIn(DirectoryRemoveRecFlag_T, aFlags), IProgress **aProgress);
+ STDMETHOD(DirectoryRename)(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags));
+ STDMETHOD(DirectorySetACL)(IN_BSTR aPath, IN_BSTR aACL);
+ STDMETHOD(EnvironmentClear)(void);
+ STDMETHOD(EnvironmentGet)(IN_BSTR aName, BSTR *aValue);
+ STDMETHOD(EnvironmentSet)(IN_BSTR aName, IN_BSTR aValue);
+ STDMETHOD(EnvironmentUnset)(IN_BSTR aName);
+ STDMETHOD(FileCreateTemp)(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, IGuestFile **aFile);
+ STDMETHOD(FileExists)(IN_BSTR aPath, BOOL *aExists);
+ STDMETHOD(FileRemove)(IN_BSTR aPath);
+ STDMETHOD(FileOpen)(IN_BSTR aPath, IN_BSTR aOpenMode, IN_BSTR aDisposition, ULONG aCreationMode, LONG64 aOffset, IGuestFile **aFile);
+ STDMETHOD(FileQueryInfo)(IN_BSTR aPath, IGuestFsObjInfo **aInfo);
+ STDMETHOD(FileQuerySize)(IN_BSTR aPath, LONG64 *aSize);
+ STDMETHOD(FileRename)(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags));
+ STDMETHOD(FileSetACL)(IN_BSTR aPath, IN_BSTR aACL);
+ STDMETHOD(ProcessCreate)(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
+ ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, IGuestProcess **aProcess);
+ STDMETHOD(ProcessCreateEx)(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
+ ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
+ ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity),
+ IGuestProcess **aProcess);
+ STDMETHOD(ProcessGet)(ULONG aPID, IGuestProcess **aProcess);
+ STDMETHOD(SymlinkCreate)(IN_BSTR aSource, IN_BSTR aTarget, SymlinkType_T aType);
+ STDMETHOD(SymlinkExists)(IN_BSTR aSymlink, BOOL *aExists);
+ STDMETHOD(SymlinkRead)(IN_BSTR aSymlink, ComSafeArrayIn(SymlinkReadFlag_T, aFlags), BSTR *aTarget);
+ STDMETHOD(SymlinkRemoveDirectory)(IN_BSTR aPath);
+ STDMETHOD(SymlinkRemoveFile)(IN_BSTR aFile);
+ /** @} */
+
+private:
+
+ typedef std::vector <ComObjPtr<GuestDirectory> > SessionDirectories;
+ typedef std::vector <ComObjPtr<GuestFile> > SessionFiles;
+ /** Map of guest processes. The key specifies the internal process number.
+ * To retrieve the process' guest PID use the Id() method of the IProcess interface. */
+ typedef std::map <uint32_t, ComObjPtr<GuestProcess> > SessionProcesses;
+
+public:
+ /** @name Public internal methods.
+ * @{ */
+ int directoryRemoveFromList(GuestDirectory *pDirectory);
+ int directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc);
+ int objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath, bool fDirectory, const Utf8Str &strName, int *pGuestRc);
+ int directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory);
+ int directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc);
+ int dispatchToProcess(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData);
+ int fileRemoveFromList(GuestFile *pFile);
+ int fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc);
+ int fileOpenInternal(const Utf8Str &strPath, const Utf8Str &strOpenMode, const Utf8Str &strDisposition,
+ uint32_t uCreationMode, int64_t iOffset, ComObjPtr<GuestFile> &pFile, int *pGuestRc);
+ int fileQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc);
+ int fileQuerySizeInternal(const Utf8Str &strPath, int64_t *pllSize, int *pGuestRc);
+ int fsQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc);
+ const GuestCredentials &getCredentials(void);
+ const GuestEnvironment &getEnvironment(void);
+ Utf8Str getName(void);
+ ULONG getId(void) { return mData.mId; }
+ Guest *getParent(void) { return mData.mParent; }
+ uint32_t getProtocolVersion(void) { return mData.mProtocolVersion; }
+ int processRemoveFromList(GuestProcess *pProcess);
+ int processCreateExInteral(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProgress);
+ inline bool processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess);
+ inline int processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess);
+ int startTaskAsync(const Utf8Str &strTaskDesc, GuestSessionTask *pTask, ComObjPtr<Progress> &pProgress);
+ int queryInfo(void);
+ /** @} */
+
+private:
+
+ struct Data
+ {
+ /** Guest control protocol version to be used.
+ * Guest Additions < VBox 4.2 have version 1,
+ * any newer version will have version 2. */
+ uint32_t mProtocolVersion;
+ /** Flag indicating if this is an internal session
+ * or not. Internal session are not accessible by clients. */
+ bool fInternal;
+ /** Pointer to the parent (Guest). */
+ Guest *mParent;
+ /** The session credentials. */
+ GuestCredentials mCredentials;
+ /** The (optional) session name. */
+ Utf8Str mName;
+ /** The session ID. */
+ ULONG mId;
+ /** The session timeout. Default is 30s. */
+ ULONG mTimeout;
+ /** The session's environment block. Can be
+ * overwritten/extended by ProcessCreate(Ex). */
+ GuestEnvironment mEnvironment;
+ /** Directory objects bound to this session. */
+ SessionDirectories mDirectories;
+ /** File objects bound to this session. */
+ SessionFiles mFiles;
+ /** Process objects bound to this session. */
+ SessionProcesses mProcesses;
+ /** Total number of session objects (processes,
+ * files, ...). */
+ uint32_t mNumObjects;
+ } mData;
+};
+
+#endif /* !____H_GUESTSESSIONIMPL */
+
diff --git a/src/VBox/Main/include/HashedPw.h b/src/VBox/Main/include/HashedPw.h
new file mode 100644
index 000000000..3e3ac1ac1
--- /dev/null
+++ b/src/VBox/Main/include/HashedPw.h
@@ -0,0 +1,27 @@
+/* $Id: HashedPw.h $ */
+/** @file
+ * Main - Password Hashing
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___HashedPw_h___
+#define ___HashedPw_h___
+
+#include <iprt/cpp/ministring.h>
+
+bool VBoxIsPasswordHashed(RTCString const *a_pstrPassword);
+void VBoxHashPassword(RTCString *a_pstrPassword);
+
+#endif
+
diff --git a/src/VBox/Main/include/HostImpl.h b/src/VBox/Main/include/HostImpl.h
index 516065ff8..56decbfc3 100644
--- a/src/VBox/Main/include/HostImpl.h
+++ b/src/VBox/Main/include/HostImpl.h
@@ -144,8 +144,11 @@ private:
bool validateDevice(const char *deviceNode, bool isCDROM);
#endif
+ HRESULT updateNetIfList();
+
#ifdef VBOX_WITH_RESOURCE_USAGE_API
void registerMetrics(PerformanceCollector *aCollector);
+ void registerDiskMetrics(PerformanceCollector *aCollector);
void unregisterMetrics(PerformanceCollector *aCollector);
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
diff --git a/src/VBox/Main/include/HostNetworkInterfaceImpl.h b/src/VBox/Main/include/HostNetworkInterfaceImpl.h
index 0d8306cdb..54449c334 100644
--- a/src/VBox/Main/include/HostNetworkInterfaceImpl.h
+++ b/src/VBox/Main/include/HostNetworkInterfaceImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2009 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -37,59 +37,65 @@ public:
VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(HostNetworkInterface, IHostNetworkInterface)
- DECLARE_NOT_AGGREGATABLE (HostNetworkInterface)
+ DECLARE_NOT_AGGREGATABLE(HostNetworkInterface)
DECLARE_PROTECT_FINAL_CONSTRUCT()
- BEGIN_COM_MAP (HostNetworkInterface)
+ BEGIN_COM_MAP(HostNetworkInterface)
VBOX_DEFAULT_INTERFACE_ENTRIES(IHostNetworkInterface)
END_COM_MAP()
- DECLARE_EMPTY_CTOR_DTOR (HostNetworkInterface)
+ DECLARE_EMPTY_CTOR_DTOR(HostNetworkInterface)
HRESULT FinalConstruct();
void FinalRelease();
// public initializer/uninitializer for internal purposes only
- HRESULT init (Bstr interfaceName, Guid guid, HostNetworkInterfaceType_T ifType);
+ HRESULT init(Bstr interfaceName, Bstr shortName, Guid guid, HostNetworkInterfaceType_T ifType);
#ifdef VBOX_WITH_HOSTNETIF_API
- HRESULT init (Bstr aInterfaceName, HostNetworkInterfaceType_T ifType, struct NETIFINFO *pIfs);
- HRESULT updateConfig ();
+ HRESULT init(Bstr aInterfaceName, HostNetworkInterfaceType_T ifType, struct NETIFINFO *pIfs);
+ HRESULT updateConfig();
#endif
// IHostNetworkInterface properties
- STDMETHOD(COMGETTER(Name)) (BSTR *aInterfaceName);
- STDMETHOD(COMGETTER(Id)) (BSTR *aGuid);
- STDMETHOD(COMGETTER(DhcpEnabled)) (BOOL *aDhcpEnabled);
- STDMETHOD(COMGETTER(IPAddress)) (BSTR *aIPAddress);
- STDMETHOD(COMGETTER(NetworkMask)) (BSTR *aNetworkMask);
- STDMETHOD(COMGETTER(IPV6Supported)) (BOOL *aIPV6Supported);
- STDMETHOD(COMGETTER(IPV6Address)) (BSTR *aIPV6Address);
- STDMETHOD(COMGETTER(IPV6NetworkMaskPrefixLength)) (ULONG *aIPV6NetworkMaskPrefixLength);
- STDMETHOD(COMGETTER(HardwareAddress)) (BSTR *aHardwareAddress);
- STDMETHOD(COMGETTER(MediumType)) (HostNetworkInterfaceMediumType_T *aType);
- STDMETHOD(COMGETTER(Status)) (HostNetworkInterfaceStatus_T *aStatus);
- STDMETHOD(COMGETTER(InterfaceType)) (HostNetworkInterfaceType_T *aType);
- STDMETHOD(COMGETTER(NetworkName)) (BSTR *aNetworkName);
-
- STDMETHOD(EnableStaticIpConfig) (IN_BSTR aIPAddress, IN_BSTR aNetworkMask);
- STDMETHOD(EnableStaticIpConfigV6) (IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength);
- STDMETHOD(EnableDynamicIpConfig) ();
- STDMETHOD(DhcpRediscover) ();
+ STDMETHOD(COMGETTER(Name))(BSTR *aInterfaceName);
+ STDMETHOD(COMGETTER(Id))(BSTR *aGuid);
+ STDMETHOD(COMGETTER(DHCPEnabled))(BOOL *aDHCPEnabled);
+ STDMETHOD(COMGETTER(IPAddress))(BSTR *aIPAddress);
+ STDMETHOD(COMGETTER(NetworkMask))(BSTR *aNetworkMask);
+ STDMETHOD(COMGETTER(IPV6Supported))(BOOL *aIPV6Supported);
+ STDMETHOD(COMGETTER(IPV6Address))(BSTR *aIPV6Address);
+ STDMETHOD(COMGETTER(IPV6NetworkMaskPrefixLength))(ULONG *aIPV6NetworkMaskPrefixLength);
+ STDMETHOD(COMGETTER(HardwareAddress))(BSTR *aHardwareAddress);
+ STDMETHOD(COMGETTER(MediumType))(HostNetworkInterfaceMediumType_T *aType);
+ STDMETHOD(COMGETTER(Status))(HostNetworkInterfaceStatus_T *aStatus);
+ STDMETHOD(COMGETTER(InterfaceType))(HostNetworkInterfaceType_T *aType);
+ STDMETHOD(COMGETTER(NetworkName))(BSTR *aNetworkName);
+
+ STDMETHOD(EnableStaticIPConfig)(IN_BSTR aIPAddress, IN_BSTR aNetworkMask);
+ STDMETHOD(EnableStaticIPConfigV6)(IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength);
+ STDMETHOD(EnableDynamicIPConfig)();
+ STDMETHOD(DHCPRediscover)();
HRESULT setVirtualBox(VirtualBox *pVBox);
+ void registerMetrics(PerformanceCollector *aCollector, ComPtr<IUnknown> objptr);
+ void unregisterMetrics(PerformanceCollector *aCollector, ComPtr<IUnknown> objptr);
private:
+ Bstr composeNetworkName(const Utf8Str szShortName);
+
const Bstr mInterfaceName;
const Guid mGuid;
+ const Bstr mNetworkName;
+ const Bstr mShortName;
HostNetworkInterfaceType_T mIfType;
VirtualBox * const mVBox;
struct Data
{
- Data() : IPAddress (0), networkMask (0), dhcpEnabled(FALSE),
- mediumType (HostNetworkInterfaceMediumType_Unknown),
+ Data() : IPAddress(0), networkMask(0), dhcpEnabled(FALSE),
+ mediumType(HostNetworkInterfaceMediumType_Unknown),
status(HostNetworkInterfaceStatus_Down){}
ULONG IPAddress;
@@ -104,9 +110,12 @@ private:
Bstr hardwareAddress;
HostNetworkInterfaceMediumType_T mediumType;
HostNetworkInterfaceStatus_T status;
+ ULONG speedMbits;
} m;
};
+typedef std::list<ComObjPtr<HostNetworkInterface> > HostNetworkInterfaceList;
+
#endif // ____H_H_HOSTNETWORKINTERFACEIMPL
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/include/Logging.h b/src/VBox/Main/include/Logging.h
index a01737983..c6385e228 100644
--- a/src/VBox/Main/include/Logging.h
+++ b/src/VBox/Main/include/Logging.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2004-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -43,8 +43,5 @@
#include <VBox/log.h>
-int VBoxSVCLogRelCreate(const char *pszLogFile, uint32_t cHistory,
- uint32_t uHistoryFileTime, uint64_t uHistoryFileSize);
-
#endif // ____H_LOGGING
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/include/MachineDebuggerImpl.h b/src/VBox/Main/include/MachineDebuggerImpl.h
index b17c086b6..d92cbe286 100644
--- a/src/VBox/Main/include/MachineDebuggerImpl.h
+++ b/src/VBox/Main/include/MachineDebuggerImpl.h
@@ -21,6 +21,7 @@
#define ____H_MACHINEDEBUGGER
#include "VirtualBoxBase.h"
+#include <iprt/log.h>
class Console;
@@ -50,30 +51,33 @@ public:
void uninit();
// IMachineDebugger properties
- STDMETHOD(COMGETTER(Singlestep)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(Singlestep)) (BOOL aEnable);
- STDMETHOD(COMGETTER(RecompileUser)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(RecompileUser)) (BOOL aEnable);
- STDMETHOD(COMGETTER(RecompileSupervisor)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(RecompileSupervisor)) (BOOL aEnable);
- STDMETHOD(COMGETTER(PATMEnabled)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(PATMEnabled)) (BOOL aEnable);
- STDMETHOD(COMGETTER(CSAMEnabled)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(CSAMEnabled)) (BOOL aEnable);
- STDMETHOD(COMGETTER(LogEnabled)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(LogEnabled)) (BOOL aEnable);
- STDMETHOD(COMGETTER(LogFlags)) (BSTR *a_pbstrSettings);
- STDMETHOD(COMGETTER(LogGroups)) (BSTR *a_pbstrSettings);
- STDMETHOD(COMGETTER(LogDestinations)) (BSTR *a_pbstrSettings);
- STDMETHOD(COMGETTER(HWVirtExEnabled)) (BOOL *aEnabled);
- STDMETHOD(COMGETTER(HWVirtExNestedPagingEnabled)) (BOOL *aEnabled);
- STDMETHOD(COMGETTER(HWVirtExVPIDEnabled)) (BOOL *aEnabled);
- STDMETHOD(COMGETTER(PAEEnabled)) (BOOL *aEnabled);
+ STDMETHOD(COMGETTER(SingleStep))(BOOL *a_pfEnabled);
+ STDMETHOD(COMSETTER(SingleStep))(BOOL a_fEnable);
+ STDMETHOD(COMGETTER(RecompileUser))(BOOL *a_pfEnabled);
+ STDMETHOD(COMSETTER(RecompileUser))(BOOL a_fEnable);
+ STDMETHOD(COMGETTER(RecompileSupervisor))(BOOL *a_pfEnabled);
+ STDMETHOD(COMSETTER(RecompileSupervisor))(BOOL a_fEnable);
+ STDMETHOD(COMGETTER(PATMEnabled))(BOOL *a_pfEnabled);
+ STDMETHOD(COMSETTER(PATMEnabled))(BOOL a_fEnable);
+ STDMETHOD(COMGETTER(CSAMEnabled))(BOOL *a_pfEnabled);
+ STDMETHOD(COMSETTER(CSAMEnabled))(BOOL a_fEnable);
+ STDMETHOD(COMGETTER(LogEnabled))(BOOL *a_pfEnabled);
+ STDMETHOD(COMSETTER(LogEnabled))(BOOL a_fEnable);
+ STDMETHOD(COMGETTER(LogDbgFlags))(BSTR *a_pbstrSettings);
+ STDMETHOD(COMGETTER(LogDbgGroups))(BSTR *a_pbstrSettings);
+ STDMETHOD(COMGETTER(LogDbgDestinations))(BSTR *a_pbstrSettings);
+ STDMETHOD(COMGETTER(LogRelFlags))(BSTR *a_pbstrSettings);
+ STDMETHOD(COMGETTER(LogRelGroups))(BSTR *a_pbstrSettings);
+ STDMETHOD(COMGETTER(LogRelDestinations))(BSTR *a_pbstrSettings);
+ STDMETHOD(COMGETTER(HWVirtExEnabled))(BOOL *a_pfEnabled);
+ STDMETHOD(COMGETTER(HWVirtExNestedPagingEnabled))(BOOL *a_pfEnabled);
+ STDMETHOD(COMGETTER(HWVirtExVPIDEnabled))(BOOL *a_pfEnabled);
+ STDMETHOD(COMGETTER(PAEEnabled))(BOOL *a_pfEnabled);
STDMETHOD(COMGETTER(OSName))(BSTR *a_pbstrName);
STDMETHOD(COMGETTER(OSVersion))(BSTR *a_pbstrVersion);
- STDMETHOD(COMGETTER(VirtualTimeRate)) (ULONG *aPct);
- STDMETHOD(COMSETTER(VirtualTimeRate)) (ULONG aPct);
- STDMETHOD(COMGETTER(VM)) (LONG64 *aVm);
+ STDMETHOD(COMGETTER(VirtualTimeRate))(ULONG *a_puPct);
+ STDMETHOD(COMSETTER(VirtualTimeRate))(ULONG a_uPct);
+ STDMETHOD(COMGETTER(VM))(LONG64 *a_u64Vm);
// IMachineDebugger methods
STDMETHOD(DumpGuestCore)(IN_BSTR a_bstrFilename, IN_BSTR a_bstrCompression);
@@ -105,10 +109,17 @@ private:
// private methods
bool queueSettings() const;
+ /** RTLogGetFlags, RTLogGetGroupSettings and RTLogGetDestinations function. */
+ typedef DECLCALLBACK(int) FNLOGGETSTR(PRTLOGGER, char *, size_t);
+ /** Function pointer. */
+ typedef FNLOGGETSTR *PFNLOGGETSTR;
+ HRESULT logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr, const char *pszLogGetStr, BSTR *a_bstrSettings);
+
Console * const mParent;
- // flags whether settings have been queued because
- // they could not be sent to the VM (not up yet, etc.)
- int mSinglestepQueued;
+ /** @name Flags whether settings have been queued because they could not be sent
+ * to the VM (not up yet, etc.)
+ * @{ */
+ int mSingleStepQueued;
int mRecompileUserQueued;
int mRecompileSupervisorQueued;
int mPatmEnabledQueued;
@@ -116,6 +127,7 @@ private:
int mLogEnabledQueued;
uint32_t mVirtualTimeRateQueued;
bool mFlushMode;
+ /** @} */
};
#endif /* !____H_MACHINEDEBUGGER */
diff --git a/src/VBox/Main/include/MachineImpl.h b/src/VBox/Main/include/MachineImpl.h
index 51186baa3..7d6203ec3 100644
--- a/src/VBox/Main/include/MachineImpl.h
+++ b/src/VBox/Main/include/MachineImpl.h
@@ -1,10 +1,10 @@
/* $Id: MachineImpl.h $ */
/** @file
- * VirtualBox COM class implementation
+ * Implementation of IMachine in VBoxSVC - Header.
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -23,7 +23,7 @@
#include "ProgressImpl.h"
#include "VRDEServerImpl.h"
#include "MediumAttachmentImpl.h"
-#include "PciDeviceAttachmentImpl.h"
+#include "PCIDeviceAttachmentImpl.h"
#include "MediumLock.h"
#include "NetworkAdapterImpl.h"
#include "AudioAdapterImpl.h"
@@ -49,6 +49,7 @@
#include <iprt/time.h>
#include <list>
+#include <vector>
// defines
////////////////////////////////////////////////////////////////////////////////
@@ -93,7 +94,10 @@ public:
enum StateDependency
{
- AnyStateDep = 0, MutableStateDep, MutableOrSavedStateDep
+ AnyStateDep = 0,
+ MutableStateDep,
+ MutableOrSavedStateDep,
+ OfflineStateDep
};
/**
@@ -134,7 +138,7 @@ public:
* to finalize the launchVMProcess() request (i.e., PID of the
* process created by launchVMProcess())
*/
- RTPROCESS mPid;
+ RTPROCESS mPID;
/** Current session state */
SessionState_T mState;
@@ -253,6 +257,10 @@ public:
ULONG mMemoryBalloonSize;
BOOL mPageFusionEnabled;
ULONG mVRAMSize;
+ ULONG mVideoCaptureWidth;
+ ULONG mVideoCaptureHeight;
+ Bstr mVideoCaptureFile;
+ BOOL mVideoCaptureEnabled;
ULONG mMonitorCount;
BOOL mHWVirtExEnabled;
BOOL mHWVirtExExclusive;
@@ -267,7 +275,7 @@ public:
BOOL mCPUHotPlugEnabled;
ULONG mCpuExecutionCap;
BOOL mAccelerate3DEnabled;
- BOOL mHpetEnabled;
+ BOOL mHPETEnabled;
BOOL mCPUAttached[SchemaDefs::MaxCPUCount];
@@ -276,26 +284,30 @@ public:
DeviceType_T mBootOrder[SchemaDefs::MaxBootPosition];
- typedef std::list< ComObjPtr<SharedFolder> > SharedFolderList;
+ typedef std::list<ComObjPtr<SharedFolder> > SharedFolderList;
SharedFolderList mSharedFolders;
ClipboardMode_T mClipboardMode;
+ DragAndDropMode_T mDragAndDropMode;
typedef std::list<GuestProperty> GuestPropertyList;
GuestPropertyList mGuestProperties;
Utf8Str mGuestPropertyNotificationPatterns;
FirmwareType_T mFirmwareType;
- KeyboardHidType_T mKeyboardHidType;
- PointingHidType_T mPointingHidType;
+ KeyboardHIDType_T mKeyboardHIDType;
+ PointingHIDType_T mPointingHIDType;
ChipsetType_T mChipsetType;
BOOL mEmulatedUSBCardReaderEnabled;
- BOOL mIoCacheEnabled;
- ULONG mIoCacheSize;
+ BOOL mIOCacheEnabled;
+ ULONG mIOCacheSize;
- typedef std::list< ComObjPtr<PciDeviceAttachment> > PciDeviceAssignmentList;
- PciDeviceAssignmentList mPciDeviceAssignments;
+ typedef std::list<ComObjPtr<PCIDeviceAttachment> > PCIDeviceAssignmentList;
+ PCIDeviceAssignmentList mPCIDeviceAssignments;
+
+ settings::Debugging mDebugging;
+ settings::Autostart mAutostart;
};
/**
@@ -312,7 +324,7 @@ public:
MediaData();
~MediaData();
- typedef std::list< ComObjPtr<MediumAttachment> > AttachmentList;
+ typedef std::list<ComObjPtr<MediumAttachment> > AttachmentList;
AttachmentList mAttachments;
};
@@ -337,14 +349,16 @@ public:
HRESULT init(VirtualBox *aParent,
const Utf8Str &strConfigFile,
const Utf8Str &strName,
+ const StringsList &llGroups,
GuestOSType *aOsType,
const Guid &aId,
- bool fForceOverwrite);
+ bool fForceOverwrite,
+ bool fDirectoryIncludesUUID);
// initializer for loading existing machine XML (either registered or not)
- HRESULT init(VirtualBox *aParent,
- const Utf8Str &strConfigFile,
- const Guid *aId);
+ HRESULT initFromSettings(VirtualBox *aParent,
+ const Utf8Str &strConfigFile,
+ const Guid *aId);
// initializer for machine config in memory (OVF import)
HRESULT init(VirtualBox *aParent,
@@ -376,6 +390,8 @@ public:
STDMETHOD(COMGETTER(Description))(BSTR *aDescription);
STDMETHOD(COMSETTER(Description))(IN_BSTR aDescription);
STDMETHOD(COMGETTER(Id))(BSTR *aId);
+ STDMETHOD(COMGETTER(Groups))(ComSafeArrayOut(BSTR, aGroups));
+ STDMETHOD(COMSETTER(Groups))(ComSafeArrayIn(IN_BSTR, aGroups));
STDMETHOD(COMGETTER(OSTypeId))(BSTR *aOSTypeId);
STDMETHOD(COMSETTER(OSTypeId))(IN_BSTR aOSTypeId);
STDMETHOD(COMGETTER(HardwareVersion))(BSTR *aVersion);
@@ -394,14 +410,22 @@ public:
STDMETHOD(COMSETTER(EmulatedUSBCardReaderEnabled))(BOOL enabled);
STDMETHOD(COMGETTER(EmulatedUSBWebcameraEnabled))(BOOL *enabled);
STDMETHOD(COMSETTER(EmulatedUSBWebcameraEnabled))(BOOL enabled);
- STDMETHOD(COMGETTER(HpetEnabled))(BOOL *enabled);
- STDMETHOD(COMSETTER(HpetEnabled))(BOOL enabled);
+ STDMETHOD(COMGETTER(HPETEnabled))(BOOL *enabled);
+ STDMETHOD(COMSETTER(HPETEnabled))(BOOL enabled);
STDMETHOD(COMGETTER(MemoryBalloonSize))(ULONG *memoryBalloonSize);
STDMETHOD(COMSETTER(MemoryBalloonSize))(ULONG memoryBalloonSize);
STDMETHOD(COMGETTER(PageFusionEnabled))(BOOL *enabled);
STDMETHOD(COMSETTER(PageFusionEnabled))(BOOL enabled);
STDMETHOD(COMGETTER(VRAMSize))(ULONG *memorySize);
STDMETHOD(COMSETTER(VRAMSize))(ULONG memorySize);
+ STDMETHOD(COMGETTER(VideoCaptureEnabled))(BOOL *u8VideoRecEnabled);
+ STDMETHOD(COMSETTER(VideoCaptureEnabled))(BOOL u8VideoRecEnabled);
+ STDMETHOD(COMGETTER(VideoCaptureFile))(BSTR * ppChVideoRecFilename);
+ STDMETHOD(COMSETTER(VideoCaptureFile))(IN_BSTR pChVideoRecFilename);
+ STDMETHOD(COMGETTER(VideoCaptureWidth))(ULONG *u32VideoRecHorzRes);
+ STDMETHOD(COMSETTER(VideoCaptureWidth))(ULONG u32VideoRecHorzRes);
+ STDMETHOD(COMGETTER(VideoCaptureHeight))(ULONG *u32VideoRecVertRes);
+ STDMETHOD(COMSETTER(VideoCaptureHeight))(ULONG u32VideoRecVertRes);
STDMETHOD(COMGETTER(MonitorCount))(ULONG *monitorCount);
STDMETHOD(COMSETTER(MonitorCount))(ULONG monitorCount);
STDMETHOD(COMGETTER(Accelerate3DEnabled))(BOOL *enabled);
@@ -419,7 +443,7 @@ public:
STDMETHOD(COMGETTER(SettingsModified))(BOOL *aModified);
STDMETHOD(COMGETTER(SessionState))(SessionState_T *aSessionState);
STDMETHOD(COMGETTER(SessionType))(BSTR *aSessionType);
- STDMETHOD(COMGETTER(SessionPid))(ULONG *aSessionPid);
+ STDMETHOD(COMGETTER(SessionPID))(ULONG *aSessionPID);
STDMETHOD(COMGETTER(State))(MachineState_T *machineState);
STDMETHOD(COMGETTER(LastStateChange))(LONG64 *aLastStateChange);
STDMETHOD(COMGETTER(StateFilePath))(BSTR *aStateFilePath);
@@ -430,6 +454,8 @@ public:
STDMETHOD(COMGETTER(SharedFolders))(ComSafeArrayOut(ISharedFolder *, aSharedFolders));
STDMETHOD(COMGETTER(ClipboardMode))(ClipboardMode_T *aClipboardMode);
STDMETHOD(COMSETTER(ClipboardMode))(ClipboardMode_T aClipboardMode);
+ STDMETHOD(COMGETTER(DragAndDropMode))(DragAndDropMode_T *aDragAndDropMode);
+ STDMETHOD(COMSETTER(DragAndDropMode))(DragAndDropMode_T aDragAndDropMode);
STDMETHOD(COMGETTER(GuestPropertyNotificationPatterns))(BSTR *aPattern);
STDMETHOD(COMSETTER(GuestPropertyNotificationPatterns))(IN_BSTR aPattern);
STDMETHOD(COMGETTER(StorageControllers))(ComSafeArrayOut(IStorageController *, aStorageControllers));
@@ -453,20 +479,32 @@ public:
STDMETHOD(COMSETTER(FaultToleranceSyncInterval))(ULONG aInterval);
STDMETHOD(COMGETTER(RTCUseUTC))(BOOL *aEnabled);
STDMETHOD(COMSETTER(RTCUseUTC))(BOOL aEnabled);
- STDMETHOD(COMGETTER(FirmwareType)) (FirmwareType_T *aFirmware);
- STDMETHOD(COMSETTER(FirmwareType)) (FirmwareType_T aFirmware);
- STDMETHOD(COMGETTER(KeyboardHidType)) (KeyboardHidType_T *aKeyboardHidType);
- STDMETHOD(COMSETTER(KeyboardHidType)) (KeyboardHidType_T aKeyboardHidType);
- STDMETHOD(COMGETTER(PointingHidType)) (PointingHidType_T *aPointingHidType);
- STDMETHOD(COMSETTER(PointingHidType)) (PointingHidType_T aPointingHidType);
- STDMETHOD(COMGETTER(ChipsetType)) (ChipsetType_T *aChipsetType);
- STDMETHOD(COMSETTER(ChipsetType)) (ChipsetType_T aChipsetType);
- STDMETHOD(COMGETTER(IoCacheEnabled)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(IoCacheEnabled)) (BOOL aEnabled);
- STDMETHOD(COMGETTER(IoCacheSize)) (ULONG *aIoCacheSize);
- STDMETHOD(COMSETTER(IoCacheSize)) (ULONG aIoCacheSize);
- STDMETHOD(COMGETTER(PciDeviceAssignments))(ComSafeArrayOut(IPciDeviceAttachment *, aAssignments));
+ STDMETHOD(COMGETTER(FirmwareType))(FirmwareType_T *aFirmware);
+ STDMETHOD(COMSETTER(FirmwareType))(FirmwareType_T aFirmware);
+ STDMETHOD(COMGETTER(KeyboardHIDType))(KeyboardHIDType_T *aKeyboardHIDType);
+ STDMETHOD(COMSETTER(KeyboardHIDType))(KeyboardHIDType_T aKeyboardHIDType);
+ STDMETHOD(COMGETTER(PointingHIDType))(PointingHIDType_T *aPointingHIDType);
+ STDMETHOD(COMSETTER(PointingHIDType))(PointingHIDType_T aPointingHIDType);
+ STDMETHOD(COMGETTER(ChipsetType))(ChipsetType_T *aChipsetType);
+ STDMETHOD(COMSETTER(ChipsetType))(ChipsetType_T aChipsetType);
+ STDMETHOD(COMGETTER(IOCacheEnabled))(BOOL *aEnabled);
+ STDMETHOD(COMSETTER(IOCacheEnabled))(BOOL aEnabled);
+ STDMETHOD(COMGETTER(IOCacheSize))(ULONG *aIOCacheSize);
+ STDMETHOD(COMSETTER(IOCacheSize))(ULONG aIOCacheSize);
+ STDMETHOD(COMGETTER(PCIDeviceAssignments))(ComSafeArrayOut(IPCIDeviceAttachment *, aAssignments));
STDMETHOD(COMGETTER(BandwidthControl))(IBandwidthControl **aBandwidthControl);
+ STDMETHOD(COMGETTER(TracingEnabled))(BOOL *pfEnabled);
+ STDMETHOD(COMSETTER(TracingEnabled))(BOOL fEnabled);
+ STDMETHOD(COMGETTER(TracingConfig))(BSTR *pbstrConfig);
+ STDMETHOD(COMSETTER(TracingConfig))(IN_BSTR bstrConfig);
+ STDMETHOD(COMGETTER(AllowTracingToAccessVM))(BOOL *pfAllow);
+ STDMETHOD(COMSETTER(AllowTracingToAccessVM))(BOOL fAllow);
+ STDMETHOD(COMGETTER(AutostartEnabled))(BOOL *pfEnabled);
+ STDMETHOD(COMSETTER(AutostartEnabled))(BOOL fEnabled);
+ STDMETHOD(COMGETTER(AutostartDelay))(ULONG *puDelay);
+ STDMETHOD(COMSETTER(AutostartDelay))(ULONG uDelay);
+ STDMETHOD(COMGETTER(AutostopType))(AutostopType_T *penmAutostopType);
+ STDMETHOD(COMSETTER(AutostopType))(AutostopType_T enmAutostopType);
// IMachine methods
STDMETHOD(LockMachine)(ISession *aSession, LockType_T lockType);
@@ -474,16 +512,23 @@ public:
STDMETHOD(SetBootOrder)(ULONG aPosition, DeviceType_T aDevice);
STDMETHOD(GetBootOrder)(ULONG aPosition, DeviceType_T *aDevice);
+ STDMETHOD(AttachDeviceWithoutMedium)(IN_BSTR aControllerName, LONG aControllerPort,
+ LONG aDevice, DeviceType_T aType);
STDMETHOD(AttachDevice)(IN_BSTR aControllerName, LONG aControllerPort,
LONG aDevice, DeviceType_T aType, IMedium *aMedium);
STDMETHOD(DetachDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice);
STDMETHOD(PassthroughDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aPassthrough);
STDMETHOD(TemporaryEjectDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aTempEject);
STDMETHOD(NonRotationalDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aNonRotational);
+ STDMETHOD(SetAutoDiscardForDevice)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice, BOOL aDiscard);
+ STDMETHOD(SetNoBandwidthGroupForDevice)(IN_BSTR aControllerName, LONG aControllerPort,
+ LONG aDevice);
STDMETHOD(SetBandwidthGroupForDevice)(IN_BSTR aControllerName, LONG aControllerPort,
LONG aDevice, IBandwidthGroup *aBandwidthGroup);
STDMETHOD(MountMedium)(IN_BSTR aControllerName, LONG aControllerPort,
LONG aDevice, IMedium *aMedium, BOOL aForce);
+ STDMETHOD(UnmountMedium)(IN_BSTR aControllerName, LONG aControllerPort,
+ LONG aDevice, BOOL aForce);
STDMETHOD(GetMedium)(IN_BSTR aControllerName, LONG aControllerPort, LONG aDevice,
IMedium **aMedium);
STDMETHOD(GetSerialPort)(ULONG slot, ISerialPort **port);
@@ -515,6 +560,7 @@ public:
STDMETHOD(GetGuestPropertyTimestamp)(IN_BSTR aName, LONG64 *aTimestamp);
STDMETHOD(SetGuestProperty)(IN_BSTR aName, IN_BSTR aValue, IN_BSTR aFlags);
STDMETHOD(SetGuestPropertyValue)(IN_BSTR aName, IN_BSTR aValue);
+ STDMETHOD(DeleteGuestProperty)(IN_BSTR aName);
STDMETHOD(EnumerateGuestProperties)(IN_BSTR aPattern, ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(BSTR, aValues), ComSafeArrayOut(LONG64, aTimestamps), ComSafeArrayOut(BSTR, aFlags));
STDMETHOD(GetMediumAttachmentsOfController)(IN_BSTR aName, ComSafeArrayOut(IMediumAttachment *, aAttachments));
STDMETHOD(GetMediumAttachment)(IN_BSTR aConstrollerName, LONG aControllerPort, LONG aDevice, IMediumAttachment **aAttachment);
@@ -523,7 +569,7 @@ public:
STDMETHOD(GetStorageControllerByName(IN_BSTR aName, IStorageController **storageController));
STDMETHOD(GetStorageControllerByInstance(ULONG aInstance, IStorageController **storageController));
STDMETHOD(SetStorageControllerBootable)(IN_BSTR aName, BOOL fBootable);
- STDMETHOD(QuerySavedGuestSize)(ULONG aScreenId, ULONG *puWidth, ULONG *puHeight);
+ STDMETHOD(QuerySavedGuestScreenInfo)(ULONG uScreenId, ULONG *puOriginX, ULONG *puOriginY, ULONG *puWidth, ULONG *puHeight, BOOL *pfEnabled);
STDMETHOD(QuerySavedThumbnailSize)(ULONG aScreenId, ULONG *aSize, ULONG *aWidth, ULONG *aHeight);
STDMETHOD(ReadSavedThumbnailToArray)(ULONG aScreenId, BOOL aBGR, ULONG *aWidth, ULONG *aHeight, ComSafeArrayOut(BYTE, aData));
STDMETHOD(ReadSavedThumbnailPNGToArray)(ULONG aScreenId, ULONG *aWidth, ULONG *aHeight, ComSafeArrayOut(BYTE, aData));
@@ -534,8 +580,8 @@ public:
STDMETHOD(GetCPUStatus(ULONG aCpu, BOOL *aCpuAttached));
STDMETHOD(QueryLogFilename(ULONG aIdx, BSTR *aName));
STDMETHOD(ReadLog(ULONG aIdx, LONG64 aOffset, LONG64 aSize, ComSafeArrayOut(BYTE, aData)));
- STDMETHOD(AttachHostPciDevice(LONG hostAddress, LONG desiredGuestAddress, BOOL tryToUnbind));
- STDMETHOD(DetachHostPciDevice(LONG hostAddress));
+ STDMETHOD(AttachHostPCIDevice(LONG hostAddress, LONG desiredGuestAddress, BOOL tryToUnbind));
+ STDMETHOD(DetachHostPCIDevice(LONG hostAddress));
STDMETHOD(CloneTo(IMachine *pTarget, CloneMode_T mode, ComSafeArrayIn(CloneOptions_T, options), IProgress **pProgress));
// public methods only for internal purposes
@@ -639,12 +685,11 @@ public:
};
/**
- * Checks if this machine is accessible, without attempting to load the
- * config file.
+ * Returns various information about this machine.
*
- * @note This method doesn't check this object's readiness. Intended to be
- * used by ready Machine children (whose readiness is bound to the parent's
- * one) or after doing addCaller() manually.
+ * @note This method doesn't lock this object or check its readiness.
+ * Intended to be used only after doing addCaller() manually and locking it
+ * for reading.
*/
ChipsetType_T getChipsetType() const { return mHWData->mChipsetType; }
@@ -655,6 +700,8 @@ public:
void allowStateModification() { mData->m_fAllowStateModification = true; }
void disallowStateModification() { mData->m_fAllowStateModification = false; }
+ const StringsList &getGroups() const { return mUserData->s.llGroups; }
+
// callback handlers
virtual HRESULT onNetworkAdapterChange(INetworkAdapter * /* networkAdapter */, BOOL /* changeAdapter */) { return S_OK; }
virtual HRESULT onNATRedirectRuleChange(ULONG /* slot */, BOOL /* fRemove */ , IN_BSTR /* name */,
@@ -668,6 +715,8 @@ public:
virtual HRESULT onCPUExecutionCapChange(ULONG /* aExecutionCap */) { return S_OK; }
virtual HRESULT onMediumChange(IMediumAttachment * /* mediumAttachment */, BOOL /* force */) { return S_OK; }
virtual HRESULT onSharedFolderChange() { return S_OK; }
+ virtual HRESULT onClipboardModeChange(ClipboardMode_T /* aClipboardMode */) { return S_OK; }
+ virtual HRESULT onDragAndDropModeChange(DragAndDropMode_T /* aDragAndDropMode */) { return S_OK; }
virtual HRESULT onBandwidthGroupChange(IBandwidthGroup * /* aBandwidthGroup */) { return S_OK; }
virtual HRESULT onStorageDeviceChange(IMediumAttachment * /* mediumAttachment */, BOOL /* remove */) { return S_OK; }
@@ -783,7 +832,10 @@ protected:
HRESULT loadSnapshot(const settings::Snapshot &data,
const Guid &aCurSnapshotId,
Snapshot *aParentSnapshot);
- HRESULT loadHardware(const settings::Hardware &data);
+ HRESULT loadHardware(const settings::Hardware &data, const settings::Debugging *pDbg,
+ const settings::Autostart *pAutostart);
+ HRESULT loadDebugging(const settings::Debugging *pDbg);
+ HRESULT loadAutostart(const settings::Autostart *pAutostart);
HRESULT loadStorageControllers(const settings::Storage &data,
const Guid *puuidRegistry,
const Guid *puuidSnapshot);
@@ -823,21 +875,19 @@ protected:
void copyMachineDataToSettings(settings::MachineConfigFile &config);
HRESULT saveAllSnapshots(settings::MachineConfigFile &config);
- HRESULT saveHardware(settings::Hardware &data);
+ HRESULT saveHardware(settings::Hardware &data, settings::Debugging *pDbg,
+ settings::Autostart *pAutostart);
HRESULT saveStorageControllers(settings::Storage &data);
HRESULT saveStorageDevices(ComObjPtr<StorageController> aStorageController,
settings::StorageController &data);
HRESULT saveStateSettings(int aFlags);
- void addMediumToRegistry(ComObjPtr<Medium> &pMedium,
- GuidList &llRegistriesThatNeedSaving,
- Guid *puuid);
+ void addMediumToRegistry(ComObjPtr<Medium> &pMedium);
HRESULT createImplicitDiffs(IProgress *aProgress,
ULONG aWeight,
- bool aOnline,
- GuidList *pllRegistriesThatNeedSaving);
- HRESULT deleteImplicitDiffs(GuidList *pllRegistriesThatNeedSaving);
+ bool aOnline);
+ HRESULT deleteImplicitDiffs(bool aOnline);
MediumAttachment* findAttachment(const MediaData::AttachmentList &ll,
IN_BSTR aControllerName,
@@ -850,8 +900,7 @@ protected:
HRESULT detachDevice(MediumAttachment *pAttach,
AutoWriteLock &writeLock,
- Snapshot *pSnapshot,
- GuidList *pllRegistriesThatNeedSaving);
+ Snapshot *pSnapshot);
HRESULT detachAllMedia(AutoWriteLock &writeLock,
Snapshot *pSnapshot,
@@ -894,12 +943,13 @@ protected:
#endif /* VBOX_WITH_GUEST_PROPS */
#ifdef VBOX_WITH_RESOURCE_USAGE_API
+ void getDiskList(MediaList &list);
void registerMetrics(PerformanceCollector *aCollector, Machine *aMachine, RTPROCESS pid);
pm::CollectorGuest *mCollectorGuest;
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
- Machine* const mPeer;
+ Machine * const mPeer;
VirtualBox * const mParent;
@@ -919,12 +969,15 @@ protected:
const ComObjPtr<AudioAdapter> mAudioAdapter;
const ComObjPtr<USBController> mUSBController;
const ComObjPtr<BIOSSettings> mBIOSSettings;
- const ComObjPtr<NetworkAdapter> mNetworkAdapters[SchemaDefs::NetworkAdapterCount];
+ typedef std::vector<ComObjPtr<NetworkAdapter> > NetworkAdapterVector;
+ NetworkAdapterVector mNetworkAdapters;
const ComObjPtr<BandwidthControl> mBandwidthControl;
- typedef std::list< ComObjPtr<StorageController> > StorageControllerList;
+ typedef std::list<ComObjPtr<StorageController> > StorageControllerList;
Backupable<StorageControllerList> mStorageControllers;
+ uint64_t uRegistryNeedsSaving;
+
friend class SessionMachine;
friend class SnapshotMachine;
friend class Appliance;
@@ -1012,17 +1065,18 @@ public:
ComSafeArrayOut(LONG64, aTimestamps), ComSafeArrayOut(BSTR, aFlags));
STDMETHOD(PushGuestProperty)(IN_BSTR aName, IN_BSTR aValue,
LONG64 aTimestamp, IN_BSTR aFlags);
- STDMETHOD(LockMedia)() { return lockMedia(); }
- STDMETHOD(UnlockMedia)() { unlockMedia(); return S_OK; }
+ STDMETHOD(LockMedia)();
+ STDMETHOD(UnlockMedia)();
STDMETHOD(EjectMedium)(IMediumAttachment *aAttachment,
IMediumAttachment **aNewAttachment);
- STDMETHOD(ReportGuestStatistics)(ULONG aValidStats, ULONG aCpuUser,
- ULONG aCpuKernel, ULONG aCpuIdle,
- ULONG aMemTotal, ULONG aMemFree,
- ULONG aMemBalloon, ULONG aMemShared,
- ULONG aMemCache, ULONG aPageTotal,
- ULONG aAllocVMM, ULONG aFreeVMM,
- ULONG aBalloonedVMM, ULONG aSharedVMM);
+ STDMETHOD(ReportVmStatistics)(ULONG aValidStats, ULONG aCpuUser,
+ ULONG aCpuKernel, ULONG aCpuIdle,
+ ULONG aMemTotal, ULONG aMemFree,
+ ULONG aMemBalloon, ULONG aMemShared,
+ ULONG aMemCache, ULONG aPageTotal,
+ ULONG aAllocVMM, ULONG aFreeVMM,
+ ULONG aBalloonedVMM, ULONG aSharedVMM,
+ ULONG aVmNetRx, ULONG aVmNetTx);
// public methods only for internal purposes
@@ -1050,11 +1104,16 @@ public:
HRESULT onUSBDeviceDetach(IN_BSTR aId,
IVirtualBoxErrorInfo *aError);
HRESULT onSharedFolderChange();
+ HRESULT onClipboardModeChange(ClipboardMode_T aClipboardMode);
+ HRESULT onDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode);
HRESULT onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup);
HRESULT onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove);
bool hasMatchingUSBFilter(const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs);
+ HRESULT lockMedia();
+ void unlockMedia();
+
private:
struct ConsoleTaskData
@@ -1122,9 +1181,6 @@ private:
ComObjPtr<Progress> &aProgress,
bool *pfNeedsMachineSaveSettings);
- HRESULT lockMedia();
- void unlockMedia();
-
HRESULT setMachineState(MachineState_T aMachineState);
HRESULT updateMachineStateOnClient();
@@ -1191,11 +1247,13 @@ public:
HRESULT init(SessionMachine *aSessionMachine,
IN_GUID aSnapshotId,
const Utf8Str &aStateFilePath);
- HRESULT init(Machine *aMachine,
- const settings::Hardware &hardware,
- const settings::Storage &storage,
- IN_GUID aSnapshotId,
- const Utf8Str &aStateFilePath);
+ HRESULT initFromSettings(Machine *aMachine,
+ const settings::Hardware &hardware,
+ const settings::Debugging *pDbg,
+ const settings::Autostart *pAutostart,
+ const settings::Storage &storage,
+ IN_GUID aSnapshotId,
+ const Utf8Str &aStateFilePath);
void uninit();
// util::Lockable interface
@@ -1218,6 +1276,10 @@ public:
private:
Guid mSnapshotId;
+ /** This field replaces mPeer for SessionMachine instances, as having
+ * a peer reference is plain meaningless and causes many subtle problems
+ * with saving settings and the like. */
+ Machine * const mMachine;
friend class Snapshot;
};
diff --git a/src/VBox/Main/include/MediumAttachmentImpl.h b/src/VBox/Main/include/MediumAttachmentImpl.h
index e3707ac4a..819317f09 100644
--- a/src/VBox/Main/include/MediumAttachmentImpl.h
+++ b/src/VBox/Main/include/MediumAttachmentImpl.h
@@ -50,6 +50,7 @@ public:
bool fPassthrough,
bool fTempEject,
bool fNonRotational,
+ bool fDiscard,
const Utf8Str &strBandwidthGroup);
HRESULT initCopy(Machine *aParent, MediumAttachment *aThat);
void uninit();
@@ -67,6 +68,7 @@ public:
STDMETHOD(COMGETTER(TemporaryEject))(BOOL *aTemporaryEject);
STDMETHOD(COMGETTER(IsEjected))(BOOL *aIsEjected);
STDMETHOD(COMGETTER(NonRotational))(BOOL *aNonRotational);
+ STDMETHOD(COMGETTER(Discard))(BOOL *aDiscard);
STDMETHOD(COMGETTER(BandwidthGroup))(IBandwidthGroup **aBwGroup);
// public internal methods
@@ -86,6 +88,7 @@ public:
bool getPassthrough() const;
bool getTempEject() const;
bool getNonRotational() const;
+ bool getDiscard() const;
const Utf8Str& getBandwidthGroup() const;
bool matches(CBSTR aControllerName, LONG aPort, LONG aDevice);
@@ -103,6 +106,9 @@ public:
void updateNonRotational(bool aNonRotational);
/** Must be called from under this object's write lock. */
+ void updateDiscard(bool aDiscard);
+
+ /** Must be called from under this object's write lock. */
void updateEjected();
/** Must be called from under this object's write lock. */
diff --git a/src/VBox/Main/include/MediumImpl.h b/src/VBox/Main/include/MediumImpl.h
index 014afb6d0..33bff7b66 100644
--- a/src/VBox/Main/include/MediumImpl.h
+++ b/src/VBox/Main/include/MediumImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2008-2011 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -69,8 +69,7 @@ public:
HRESULT init(VirtualBox *aVirtualBox,
const Utf8Str &aFormat,
const Utf8Str &aLocation,
- const Guid &uuidMachineRegistry,
- GuidList *pllRegistriesThatNeedSaving);
+ const Guid &uuidMachineRegistry);
// initializer for opening existing media
// (VirtualBox::OpenMedium(); Machine::AttachDevice())
@@ -127,7 +126,7 @@ public:
STDMETHOD(COMGETTER(MachineIds))(ComSafeArrayOut(BSTR, aMachineIds));
// IMedium methods
- STDMETHOD(SetIDs)(BOOL aSetImageId, IN_BSTR aImageId,
+ STDMETHOD(SetIds)(BOOL aSetImageId, IN_BSTR aImageId,
BOOL aSetParentId, IN_BSTR aParentId);
STDMETHOD(RefreshState)(MediumState_T *aState);
STDMETHOD(GetSnapshotIds)(IN_BSTR aMachineId,
@@ -154,6 +153,8 @@ public:
STDMETHOD(MergeTo)(IMedium *aTarget, IProgress **aProgress);
STDMETHOD(CloneTo)(IMedium *aTarget, ULONG aVariant,
IMedium *aParent, IProgress **aProgress);
+ STDMETHOD(CloneToBase)(IMedium *aTarget, ULONG aVariant,
+ IProgress **aProgress);
STDMETHOD(Compact)(IProgress **aProgress);
STDMETHOD(Resize)(LONG64 aLogicalSize, IProgress **aProgress);
STDMETHOD(Reset)(IProgress **aProgress);
@@ -182,13 +183,16 @@ public:
bool removeRegistry(const Guid& id, bool fRecurse);
bool isInRegistry(const Guid& id);
bool getFirstRegistryMachineId(Guid &uuid) const;
- HRESULT addToRegistryIDList(GuidList &llRegistryIDs);
+ void markRegistriesModified();
+
+ HRESULT setPropertyDirect(const Utf8Str &aName, const Utf8Str &aValue);
HRESULT addBackReference(const Guid &aMachineId,
const Guid &aSnapshotId = Guid::Empty);
HRESULT removeBackReference(const Guid &aMachineId,
const Guid &aSnapshotId = Guid::Empty);
+
const Guid* getFirstMachineBackrefId() const;
const Guid* getAnyMachineBackref() const;
const Guid* getFirstMachineBackrefSnapshotId() const;
@@ -217,12 +221,11 @@ public:
MediumVariant_T aVariant,
MediumLockList *pMediumLockList,
ComObjPtr<Progress> *aProgress,
- bool aWait,
- GuidList *pllRegistriesThatNeedSaving);
+ bool aWait);
Utf8Str getPreferredDiffFormat();
- HRESULT close(GuidList *pllRegistriesThatNeedSaving, AutoCaller &autoCaller);
- HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait, GuidList *pllRegistriesThatNeedSaving);
+ HRESULT close(AutoCaller &autoCaller);
+ HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait);
HRESULT markForDeletion();
HRESULT unmarkForDeletion();
HRESULT markLockedForDeletion();
@@ -242,8 +245,7 @@ public:
const MediaList &aChildrenToReparent,
MediumLockList *aMediumLockList,
ComObjPtr<Progress> *aProgress,
- bool aWait,
- GuidList *pllRegistriesThatNeedSaving);
+ bool aWait);
void cancelMergeTo(const MediaList &aChildrenToReparent,
MediumLockList *aMediumLockList);
@@ -252,12 +254,12 @@ public:
HRESULT exportFile(const char *aFilename,
const ComObjPtr<MediumFormat> &aFormat,
MediumVariant_T aVariant,
- void *aVDImageIOCallbacks, void *aVDImageIOUser,
+ PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,
const ComObjPtr<Progress> &aProgress);
HRESULT importFile(const char *aFilename,
const ComObjPtr<MediumFormat> &aFormat,
MediumVariant_T aVariant,
- void *aVDImageIOCallbacks, void *aVDImageIOUser,
+ PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,
const ComObjPtr<Medium> &aParent,
const ComObjPtr<Progress> &aProgress);
@@ -270,7 +272,7 @@ private:
HRESULT queryInfo(bool fSetImageId, bool fSetParentId);
HRESULT canClose();
- HRESULT unregisterWithVirtualBox(GuidList *pllRegistriesThatNeedSaving);
+ HRESULT unregisterWithVirtualBox();
HRESULT setStateError();
@@ -330,7 +332,7 @@ private:
friend class ImportTask;
HRESULT startThread(Medium::Task *pTask);
- HRESULT runNow(Medium::Task *pTask, GuidList *pllRegistriesThatNeedSaving);
+ HRESULT runNow(Medium::Task *pTask);
HRESULT taskCreateBaseHandler(Medium::CreateBaseTask &task);
HRESULT taskCreateDiffHandler(Medium::CreateDiffTask &task);
diff --git a/src/VBox/Main/include/NATEngineImpl.h b/src/VBox/Main/include/NATEngineImpl.h
index 2f2485e0c..c0aae9382 100644
--- a/src/VBox/Main/include/NATEngineImpl.h
+++ b/src/VBox/Main/include/NATEngineImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2009 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -17,8 +17,8 @@
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
-#ifndef ____H_NATDRIVER
-#define ____H_NATDRIVER
+#ifndef ____H_NATENGINE
+#define ____H_NATENGINE
#include "VirtualBoxBase.h"
@@ -42,9 +42,9 @@ class ATL_NO_VTABLE NATEngine :
mSockSnd(0),
mTcpRcv(0),
mTcpSnd(0),
- mDnsPassDomain(TRUE),
- mDnsProxy(FALSE),
- mDnsUseHostResolver(FALSE),
+ mDNSPassDomain(TRUE),
+ mDNSProxy(FALSE),
+ mDNSUseHostResolver(FALSE),
mAliasMode(0)
{}
@@ -56,13 +56,13 @@ class ATL_NO_VTABLE NATEngine :
uint32_t mTcpRcv;
uint32_t mTcpSnd;
/* TFTP service */
- Utf8Str mTftpPrefix;
- Utf8Str mTftpBootFile;
- Utf8Str mTftpNextServer;
+ Utf8Str mTFTPPrefix;
+ Utf8Str mTFTPBootFile;
+ Utf8Str mTFTPNextServer;
/* DNS service */
- BOOL mDnsPassDomain;
- BOOL mDnsProxy;
- BOOL mDnsUseHostResolver;
+ BOOL mDNSPassDomain;
+ BOOL mDNSProxy;
+ BOOL mDNSUseHostResolver;
/* Alias service */
ULONG mAliasMode;
};
@@ -73,10 +73,10 @@ class ATL_NO_VTABLE NATEngine :
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(NATEngine)
- VBOX_DEFAULT_INTERFACE_ENTRIES (INATEngine)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(INATEngine)
END_COM_MAP()
- DECLARE_EMPTY_CTOR_DTOR (NATEngine)
+ DECLARE_EMPTY_CTOR_DTOR(NATEngine)
HRESULT FinalConstruct();
HRESULT init(Machine *aParent, INetworkAdapter *aAdapter);
@@ -92,32 +92,32 @@ class ATL_NO_VTABLE NATEngine :
HRESULT loadSettings(const settings::NAT &data);
HRESULT saveSettings(settings::NAT &data);
- STDMETHOD(COMSETTER(Network)) (IN_BSTR aNetwork);
- STDMETHOD(COMGETTER(Network)) (BSTR *aNetwork);
- STDMETHOD(COMSETTER(HostIP)) (IN_BSTR aBindIP);
- STDMETHOD(COMGETTER(HostIP)) (BSTR *aBindIP);
+ STDMETHOD(COMSETTER(Network))(IN_BSTR aNetwork);
+ STDMETHOD(COMGETTER(Network))(BSTR *aNetwork);
+ STDMETHOD(COMSETTER(HostIP))(IN_BSTR aBindIP);
+ STDMETHOD(COMGETTER(HostIP))(BSTR *aBindIP);
/* TFTP attributes */
- STDMETHOD(COMSETTER(TftpPrefix)) (IN_BSTR aTftpPrefix);
- STDMETHOD(COMGETTER(TftpPrefix)) (BSTR *aTftpPrefix);
- STDMETHOD(COMSETTER(TftpBootFile)) (IN_BSTR aTftpBootFile);
- STDMETHOD(COMGETTER(TftpBootFile)) (BSTR *aTftpBootFile);
- STDMETHOD(COMSETTER(TftpNextServer)) (IN_BSTR aTftpNextServer);
- STDMETHOD(COMGETTER(TftpNextServer)) (BSTR *aTftpNextServer);
+ STDMETHOD(COMSETTER(TFTPPrefix))(IN_BSTR aTFTPPrefix);
+ STDMETHOD(COMGETTER(TFTPPrefix))(BSTR *aTFTPPrefix);
+ STDMETHOD(COMSETTER(TFTPBootFile))(IN_BSTR aTFTPBootFile);
+ STDMETHOD(COMGETTER(TFTPBootFile))(BSTR *aTFTPBootFile);
+ STDMETHOD(COMSETTER(TFTPNextServer))(IN_BSTR aTFTPNextServer);
+ STDMETHOD(COMGETTER(TFTPNextServer))(BSTR *aTFTPNextServer);
/* Alias attributes */
- STDMETHOD(COMSETTER(AliasMode)) (ULONG aAliasLog);
- STDMETHOD(COMGETTER(AliasMode)) (ULONG *aAliasLog);
+ STDMETHOD(COMSETTER(AliasMode))(ULONG aAliasLog);
+ STDMETHOD(COMGETTER(AliasMode))(ULONG *aAliasLog);
/* DNS attributes */
- STDMETHOD(COMSETTER(DnsPassDomain)) (BOOL aDnsPassDomain);
- STDMETHOD(COMGETTER(DnsPassDomain)) (BOOL *aDnsPassDomain);
- STDMETHOD(COMSETTER(DnsProxy)) (BOOL aDnsProxy);
- STDMETHOD(COMGETTER(DnsProxy)) (BOOL *aDnsProxy);
- STDMETHOD(COMGETTER(DnsUseHostResolver)) (BOOL *aDnsUseHostResolver);
- STDMETHOD(COMSETTER(DnsUseHostResolver)) (BOOL aDnsUseHostResolver);
+ STDMETHOD(COMSETTER(DNSPassDomain))(BOOL aDNSPassDomain);
+ STDMETHOD(COMGETTER(DNSPassDomain))(BOOL *aDNSPassDomain);
+ STDMETHOD(COMSETTER(DNSProxy))(BOOL aDNSProxy);
+ STDMETHOD(COMGETTER(DNSProxy))(BOOL *aDNSProxy);
+ STDMETHOD(COMGETTER(DNSUseHostResolver))(BOOL *aDNSUseHostResolver);
+ STDMETHOD(COMSETTER(DNSUseHostResolver))(BOOL aDNSUseHostResolver);
STDMETHOD(SetNetworkSettings)(ULONG aMtu, ULONG aSockSnd, ULONG aSockRcv, ULONG aTcpWndSnd, ULONG aTcpWndRcv);
STDMETHOD(GetNetworkSettings)(ULONG *aMtu, ULONG *aSockSnd, ULONG *aSockRcv, ULONG *aTcpWndSnd, ULONG *aTcpWndRcv);
- STDMETHOD(COMGETTER(Redirects)) (ComSafeArrayOut (BSTR, aNatRules));
+ STDMETHOD(COMGETTER(Redirects))(ComSafeArrayOut(BSTR, aNatRules));
STDMETHOD(AddRedirect)(IN_BSTR aName, NATProtocol_T aProto, IN_BSTR aBindIp, USHORT aHostPort, IN_BSTR aGuestIP, USHORT aGuestPort);
STDMETHOD(RemoveRedirect)(IN_BSTR aName);
diff --git a/src/VBox/Main/include/NetworkAdapterImpl.h b/src/VBox/Main/include/NetworkAdapterImpl.h
index 8eb57485b..326015495 100644
--- a/src/VBox/Main/include/NetworkAdapterImpl.h
+++ b/src/VBox/Main/include/NetworkAdapterImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -69,7 +69,7 @@ public:
Bstr mGenericDriver;
settings::StringsMap mGenericProperties;
ULONG mBootPriority;
- ComObjPtr<BandwidthGroup> mBandwidthGroup;
+ Utf8Str mBandwidthGroup;
};
VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(NetworkAdapter, INetworkAdapter)
@@ -89,7 +89,7 @@ public:
// public initializer/uninitializer for internal purposes only
HRESULT init(Machine *aParent, ULONG aSlot);
- HRESULT init(Machine *aParent, NetworkAdapter *aThat);
+ HRESULT init(Machine *aParent, NetworkAdapter *aThat, bool aReshare = false);
HRESULT initCopy(Machine *aParent, NetworkAdapter *aThat);
void uninit();
@@ -123,7 +123,7 @@ public:
STDMETHOD(COMSETTER(PromiscModePolicy))(NetworkAdapterPromiscModePolicy_T aPromiscModePolicy);
STDMETHOD(COMGETTER(TraceFile))(BSTR *aTraceFile);
STDMETHOD(COMSETTER(TraceFile))(IN_BSTR aTraceFile);
- STDMETHOD(COMGETTER(NatDriver))(INATEngine **aNatDriver);
+ STDMETHOD(COMGETTER(NATEngine))(INATEngine **aNATEngine);
STDMETHOD(COMGETTER(BootPriority))(ULONG *aBootPriority);
STDMETHOD(COMSETTER(BootPriority))(ULONG aBootPriority);
STDMETHOD(COMGETTER(BandwidthGroup))(IBandwidthGroup **aBwGroup);
@@ -147,6 +147,8 @@ public:
void copyFrom(NetworkAdapter *aThat);
void applyDefaults(GuestOSType *aOsType);
+ ComObjPtr<NetworkAdapter> getPeer();
+
private:
void generateMACAddress();
diff --git a/src/VBox/Main/include/Nvram.h b/src/VBox/Main/include/Nvram.h
new file mode 100644
index 000000000..4f95e71d2
--- /dev/null
+++ b/src/VBox/Main/include/Nvram.h
@@ -0,0 +1,46 @@
+/* $Id: Nvram.h $ */
+
+/** @file
+ * VirtualBox COM class implementation
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_NVRAM
+#define ____H_NVRAM
+
+#include <VBox/com/ptr.h>
+#include <VBox/vmm/pdmdrv.h>
+
+class Console;
+struct NVRAM;
+
+class Nvram
+{
+public:
+ Nvram(Console *console);
+ virtual ~Nvram();
+ static const PDMDRVREG DrvReg;
+ Console *getParent(void) { return mParent; }
+ struct NVRAM *mpDrv;
+
+private:
+ static DECLCALLBACK(void *) drvNvram_QueryInterface(PPDMIBASE pInterface, const char *pszIID);
+ static DECLCALLBACK(int) drvNvram_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags);
+ static DECLCALLBACK(void) drvNvram_Destruct(PPDMDRVINS pDrvIns);
+
+ Console * const mParent;
+};
+
+#endif /* !____H_NVRAM */
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/include/PciDeviceAttachmentImpl.h b/src/VBox/Main/include/PCIDeviceAttachmentImpl.h
index 8b25b905b..e162be1f9 100644
--- a/src/VBox/Main/include/PciDeviceAttachmentImpl.h
+++ b/src/VBox/Main/include/PCIDeviceAttachmentImpl.h
@@ -1,4 +1,4 @@
-/* $Id: PciDeviceAttachmentImpl.h $ */
+/* $Id: PCIDeviceAttachmentImpl.h $ */
/** @file
*
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -23,23 +23,23 @@
#include "VirtualBoxBase.h"
#include <VBox/settings.h>
-class ATL_NO_VTABLE PciAddress :
+class ATL_NO_VTABLE PCIAddress :
public VirtualBoxBase,
- VBOX_SCRIPTABLE_IMPL(IPciAddress)
+ VBOX_SCRIPTABLE_IMPL(IPCIAddress)
{
public:
- VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(PciAddress, IPciAddress)
+ VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(PCIAddress, IPCIAddress)
- DECLARE_NOT_AGGREGATABLE(PciAddress)
+ DECLARE_NOT_AGGREGATABLE(PCIAddress)
DECLARE_PROTECT_FINAL_CONSTRUCT()
- BEGIN_COM_MAP(PciAddress)
- VBOX_DEFAULT_INTERFACE_ENTRIES(IPciAddress)
+ BEGIN_COM_MAP(PCIAddress)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IPCIAddress)
END_COM_MAP()
- PciAddress() { }
- ~PciAddress() { }
+ PCIAddress() { }
+ ~PCIAddress() { }
// public initializer/uninitializer for internal purposes only
HRESULT init(LONG aAddess);
@@ -48,7 +48,7 @@ public:
HRESULT FinalConstruct();
void FinalRelease();
- // IPciAddress properties
+ // IPCIAddress properties
STDMETHOD(COMGETTER(Bus))(SHORT *aBus)
{
*aBus = mBus;
@@ -85,23 +85,23 @@ private:
SHORT mBus, mDevice, mFn;
};
-class ATL_NO_VTABLE PciDeviceAttachment :
+class ATL_NO_VTABLE PCIDeviceAttachment :
public VirtualBoxBase,
- VBOX_SCRIPTABLE_IMPL(IPciDeviceAttachment)
+ VBOX_SCRIPTABLE_IMPL(IPCIDeviceAttachment)
{
public:
- VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(PciDeviceAttachment, IPciDeviceAttachment)
+ VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(PCIDeviceAttachment, IPCIDeviceAttachment)
- DECLARE_NOT_AGGREGATABLE(PciDeviceAttachment)
+ DECLARE_NOT_AGGREGATABLE(PCIDeviceAttachment)
DECLARE_PROTECT_FINAL_CONSTRUCT()
- BEGIN_COM_MAP(PciDeviceAttachment)
- VBOX_DEFAULT_INTERFACE_ENTRIES(IPciDeviceAttachment)
+ BEGIN_COM_MAP(PCIDeviceAttachment)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IPCIDeviceAttachment)
END_COM_MAP()
- PciDeviceAttachment() { }
- ~PciDeviceAttachment() { }
+ PCIDeviceAttachment() { }
+ ~PCIDeviceAttachment() { }
// public initializer/uninitializer for internal purposes only
HRESULT init(IMachine * aParent,
@@ -114,13 +114,13 @@ public:
// settings
HRESULT loadSettings(IMachine * aParent,
- const settings::HostPciDeviceAttachment& aHpda);
- HRESULT saveSettings(settings::HostPciDeviceAttachment &data);
+ const settings::HostPCIDeviceAttachment& aHpda);
+ HRESULT saveSettings(settings::HostPCIDeviceAttachment &data);
HRESULT FinalConstruct();
void FinalRelease();
- // IPciDeviceAttachment properties
+ // IPCIDeviceAttachment properties
STDMETHOD(COMGETTER(Name))(BSTR * aName);
STDMETHOD(COMGETTER(IsPhysicalDevice))(BOOL * aPhysical);
STDMETHOD(COMGETTER(HostAddress))(LONG * hostAddress);
diff --git a/src/VBox/Main/include/PciRawDevImpl.h b/src/VBox/Main/include/PCIRawDevImpl.h
index 26e66050c..851856991 100644
--- a/src/VBox/Main/include/PciRawDevImpl.h
+++ b/src/VBox/Main/include/PCIRawDevImpl.h
@@ -1,10 +1,10 @@
-/* $Id: PciRawDevImpl.h $ */
+/* $Id: PCIRawDevImpl.h $ */
/** @file
* VirtualBox Driver interface to raw PCI device
*/
/*
- * Copyright (C) 2010-2011 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -24,11 +24,11 @@
class Console;
struct DRVMAINPCIRAWDEV;
-class PciRawDev
+class PCIRawDev
{
public:
- PciRawDev(Console *console);
- virtual ~PciRawDev();
+ PCIRawDev(Console *console);
+ virtual ~PCIRawDev();
static const PDMDRVREG DrvReg;
struct DRVMAINPCIRAWDEV *mpDrv;
@@ -44,7 +44,7 @@ class PciRawDev
static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns);
static DECLCALLBACK(void) drvReset(PPDMDRVINS pDrvIns);
static DECLCALLBACK(int) drvDeviceConstructComplete(PPDMIPCIRAWCONNECTOR pInterface, const char *pcszName,
- uint32_t uHostPciAddress, uint32_t uGuestPciAddress,
+ uint32_t uHostPCIAddress, uint32_t uGuestPCIAddress,
int rc);
diff --git a/src/VBox/Main/include/ParallelPortImpl.h b/src/VBox/Main/include/ParallelPortImpl.h
index f952f7207..4ff5e9d84 100644
--- a/src/VBox/Main/include/ParallelPortImpl.h
+++ b/src/VBox/Main/include/ParallelPortImpl.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -84,5 +84,5 @@ private:
Data *m;
};
-#endif // ____H_FLOPPYDRIVEIMPL
+#endif // ____H_PARALLELPORTIMPL
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/include/Performance.h b/src/VBox/Main/include/Performance.h
index f7de94eda..74f7a250d 100644
--- a/src/VBox/Main/include/Performance.h
+++ b/src/VBox/Main/include/Performance.h
@@ -32,6 +32,8 @@
#include <vector>
#include <queue>
+#include "MediumImpl.h"
+
/* Forward decl. */
class Machine;
@@ -39,6 +41,12 @@ namespace pm
{
/* CPU load is measured in 1/1000 of per cent. */
const uint64_t PM_CPU_LOAD_MULTIPLIER = UINT64_C(100000);
+ /* Network load is measured in 1/1000 of per cent. */
+ const uint64_t PM_NETWORK_LOAD_MULTIPLIER = UINT64_C(100000);
+ /* Disk load is measured in 1/1000 of per cent. */
+ const uint64_t PM_DISK_LOAD_MULTIPLIER = UINT64_C(100000);
+ /* Sampler precision in milliseconds. */
+ const uint64_t PM_SAMPLER_PRECISION_MS = 50;
/* Sub Metrics **********************************************************/
class CircularBuffer
@@ -62,13 +70,13 @@ namespace pm
class SubMetric : public CircularBuffer
{
public:
- SubMetric(const char *name, const char *description)
+ SubMetric(com::Utf8Str name, const char *description)
: mName(name), mDescription(description) {};
void query(ULONG *data);
- const char *getName() { return mName; };
+ const char *getName() { return mName.c_str(); };
const char *getDescription() { return mDescription; };
private:
- const char *mName;
+ const com::Utf8Str mName;
const char *mDescription;
};
@@ -147,33 +155,39 @@ namespace pm
*/
typedef enum
{
- GUESTSTATMASK_NONE = 0x00000000,
- GUESTSTATMASK_CPUUSER = 0x00000001,
- GUESTSTATMASK_CPUKERNEL = 0x00000002,
- GUESTSTATMASK_CPUIDLE = 0x00000004,
- GUESTSTATMASK_MEMTOTAL = 0x00000008,
- GUESTSTATMASK_MEMFREE = 0x00000010,
- GUESTSTATMASK_MEMBALLOON = 0x00000020,
- GUESTSTATMASK_MEMSHARED = 0x00000040,
- GUESTSTATMASK_MEMCACHE = 0x00000080,
- GUESTSTATMASK_PAGETOTAL = 0x00000100,
- GUESTSTATMASK_ALLOCVMM = 0x00000200,
- GUESTSTATMASK_FREEVMM = 0x00000400,
- GUESTSTATMASK_BALOONVMM = 0x00000800,
- GUESTSTATMASK_SHAREDVMM = 0x00001000
- } GUESTSTATMASK;
-
- const ULONG GUESTSTATS_CPULOAD =
- GUESTSTATMASK_CPUUSER|GUESTSTATMASK_CPUKERNEL|GUESTSTATMASK_CPUIDLE;
- const ULONG GUESTSTATS_RAMUSAGE =
- GUESTSTATMASK_MEMTOTAL|GUESTSTATMASK_MEMFREE|GUESTSTATMASK_MEMBALLOON|
- GUESTSTATMASK_MEMSHARED|GUESTSTATMASK_MEMCACHE|
- GUESTSTATMASK_PAGETOTAL;
- const ULONG GUESTSTATS_VMMRAM =
- GUESTSTATMASK_ALLOCVMM|GUESTSTATMASK_FREEVMM|
- GUESTSTATMASK_BALOONVMM|GUESTSTATMASK_SHAREDVMM;
- const ULONG GUESTSTATS_ALL = GUESTSTATS_CPULOAD|GUESTSTATS_RAMUSAGE|GUESTSTATS_VMMRAM;
-
+ VMSTATMASK_NONE = 0x00000000,
+ VMSTATMASK_GUEST_CPUUSER = 0x00000001,
+ VMSTATMASK_GUEST_CPUKERNEL = 0x00000002,
+ VMSTATMASK_GUEST_CPUIDLE = 0x00000004,
+ VMSTATMASK_GUEST_MEMTOTAL = 0x00000008,
+ VMSTATMASK_GUEST_MEMFREE = 0x00000010,
+ VMSTATMASK_GUEST_MEMBALLOON = 0x00000020,
+ VMSTATMASK_GUEST_MEMSHARED = 0x00000040,
+ VMSTATMASK_GUEST_MEMCACHE = 0x00000080,
+ VMSTATMASK_GUEST_PAGETOTAL = 0x00000100,
+ VMSTATMASK_VMM_ALLOC = 0x00010000,
+ VMSTATMASK_VMM_FREE = 0x00020000,
+ VMSTATMASK_VMM_BALOON = 0x00040000,
+ VMSTATMASK_VMM_SHARED = 0x00080000,
+ VMSTATMASK_NET_RX = 0x01000000,
+ VMSTATMASK_NET_TX = 0x02000000
+ } VMSTATMASK;
+
+ const ULONG VMSTATS_GUEST_CPULOAD =
+ VMSTATMASK_GUEST_CPUUSER | VMSTATMASK_GUEST_CPUKERNEL |
+ VMSTATMASK_GUEST_CPUIDLE;
+ const ULONG VMSTATS_GUEST_RAMUSAGE =
+ VMSTATMASK_GUEST_MEMTOTAL | VMSTATMASK_GUEST_MEMFREE |
+ VMSTATMASK_GUEST_MEMBALLOON | VMSTATMASK_GUEST_MEMSHARED |
+ VMSTATMASK_GUEST_MEMCACHE | VMSTATMASK_GUEST_PAGETOTAL;
+ const ULONG VMSTATS_VMM_RAM =
+ VMSTATMASK_VMM_ALLOC | VMSTATMASK_VMM_FREE|
+ VMSTATMASK_VMM_BALOON | VMSTATMASK_VMM_SHARED;
+ const ULONG VMSTATS_NET_RATE =
+ VMSTATMASK_NET_RX | VMSTATMASK_NET_TX;
+ const ULONG VMSTATS_ALL =
+ VMSTATS_GUEST_CPULOAD | VMSTATS_GUEST_RAMUSAGE |
+ VMSTATS_VMM_RAM | VMSTATS_NET_RATE;
class CollectorGuest;
class CollectorGuestRequest
@@ -259,7 +273,8 @@ namespace pm
ULONG aMemBalloon, ULONG aMemShared,
ULONG aMemCache, ULONG aPageTotal,
ULONG aAllocVMM, ULONG aFreeVMM,
- ULONG aBalloonedVMM, ULONG aSharedVMM);
+ ULONG aBalloonedVMM, ULONG aSharedVMM,
+ ULONG aVmNetRx, ULONG aVmNetTx);
int enable(ULONG mask);
int disable(ULONG mask);
@@ -283,6 +298,8 @@ namespace pm
ULONG getFreeVMM() { return mFreeVMM; };
ULONG getBalloonedVMM() { return mBalloonedVMM; };
ULONG getSharedVMM() { return mSharedVMM; };
+ ULONG getVmNetRx() { return mVmNetRx; };
+ ULONG getVmNetTx() { return mVmNetTx; };
private:
int enableVMMStats(bool mCollectVMMStats);
@@ -310,6 +327,8 @@ namespace pm
ULONG mFreeVMM;
ULONG mBalloonedVMM;
ULONG mSharedVMM;
+ ULONG mVmNetRx;
+ ULONG mVmNetTx;
};
typedef std::list<CollectorGuest*> CollectorGuestList;
@@ -337,6 +356,8 @@ namespace pm
};
/* Collector Hardware Abstraction Layer *********************************/
+ typedef std::list<RTCString> DiskList;
+
class CollectorHAL
{
public:
@@ -349,6 +370,10 @@ namespace pm
virtual int getHostCpuMHz(ULONG *mhz);
/** Returns the amount of physical memory in kilobytes. */
virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
+ /** Returns file system counters in megabytes. */
+ virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available);
+ /** Returns disk size in bytes. */
+ virtual int getHostDiskSize(const char *name, uint64_t *size);
/** Returns CPU usage in 1/1000th per cent by a particular process. */
virtual int getProcessCpuLoad(RTPROCESS process, ULONG *user, ULONG *kernel);
/** Returns the amount of memory used by a process in kilobytes. */
@@ -356,8 +381,15 @@ namespace pm
/** Returns CPU usage counters in platform-specific units. */
virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
+ /** Returns received and transmitted bytes. */
+ virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx);
+ /** Returns disk usage counters in platform-specific units. */
+ virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms);
/** Returns process' CPU usage counter in platform-specific units. */
virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
+
+ /** Returns the list of disks used by the specified file system. */
+ virtual int getDiskListByFs(const char *name, DiskList& list);
};
extern CollectorHAL *createHAL();
@@ -366,7 +398,7 @@ namespace pm
class BaseMetric
{
public:
- BaseMetric(CollectorHAL *hal, const char *name, ComPtr<IUnknown> object)
+ BaseMetric(CollectorHAL *hal, const com::Utf8Str name, ComPtr<IUnknown> object)
: mPeriod(0), mLength(0), mHAL(hal), mName(name), mObject(object),
mLastSampleTaken(0), mEnabled(false), mUnregistered(false) {};
virtual ~BaseMetric() {};
@@ -389,7 +421,7 @@ namespace pm
bool isEnabled() { return mEnabled; };
ULONG getPeriod() { return mPeriod; };
ULONG getLength() { return mLength; };
- const char *getName() { return mName; };
+ const char *getName() { return mName.c_str(); };
ComPtr<IUnknown> getObject() { return mObject; };
bool associatedWith(ComPtr<IUnknown> object) { return mObject == object; };
@@ -397,7 +429,7 @@ namespace pm
ULONG mPeriod;
ULONG mLength;
CollectorHAL *mHAL;
- const char *mName;
+ const com::Utf8Str mName;
ComPtr<IUnknown> mObject;
uint64_t mLastSampleTaken;
bool mEnabled;
@@ -486,6 +518,116 @@ namespace pm
SubMetric *mAvailable;
};
+ class HostNetworkSpeed : public BaseMetric
+ {
+ public:
+ HostNetworkSpeed(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str /* shortname */, com::Utf8Str /* ifname */, uint32_t speed, SubMetric *linkspeed)
+ : BaseMetric(hal, name, object), mSpeed(speed), mLinkSpeed(linkspeed) {};
+ ~HostNetworkSpeed() { delete mLinkSpeed; };
+
+ void init(ULONG period, ULONG length) { mPeriod = period; mLength = length; mLinkSpeed->init(length); };
+ void preCollect(CollectorHints& /* hints */, uint64_t /* iTick */) {};
+ void collect() { if (mSpeed) mLinkSpeed->put(mSpeed); };
+ const char *getUnit() { return "mbit/s"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ ULONG mSpeed;
+ SubMetric *mLinkSpeed;
+ };
+
+ class HostNetworkLoadRaw : public BaseMetric
+ {
+ public:
+ HostNetworkLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str shortname, com::Utf8Str ifname, uint32_t speed, SubMetric *rx, SubMetric *tx)
+ : BaseMetric(hal, name, object), mShortName(shortname), mInterfaceName(ifname), mRx(rx), mTx(tx), mRxPrev(0), mTxPrev(0), mRc(VINF_SUCCESS) { mSpeed = (uint64_t)speed * (1000000/8); /* Convert to bytes/sec */ };
+ ~HostNetworkLoadRaw() { delete mRx; delete mTx; };
+
+ void init(ULONG period, ULONG length);
+
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "%"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return PM_NETWORK_LOAD_MULTIPLIER; };
+ ULONG getScale() { return PM_NETWORK_LOAD_MULTIPLIER / 100; }
+
+ private:
+ com::Utf8Str mShortName;
+ com::Utf8Str mInterfaceName;
+ SubMetric *mRx;
+ SubMetric *mTx;
+ uint64_t mRxPrev;
+ uint64_t mTxPrev;
+ uint64_t mSpeed;
+ int mRc;
+ };
+
+ class HostFilesystemUsage : public BaseMetric
+ {
+ public:
+ HostFilesystemUsage(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str fsname, SubMetric *total, SubMetric *used, SubMetric *available)
+ : BaseMetric(hal, name, object), mFsName(fsname), mTotal(total), mUsed(used), mAvailable(available) {};
+ ~HostFilesystemUsage() { delete mTotal; delete mUsed; delete mAvailable; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "mB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ com::Utf8Str mFsName;
+ SubMetric *mTotal;
+ SubMetric *mUsed;
+ SubMetric *mAvailable;
+ };
+
+ class HostDiskUsage : public BaseMetric
+ {
+ public:
+ HostDiskUsage(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str diskname, SubMetric *total)
+ : BaseMetric(hal, name, object), mDiskName(diskname), mTotal(total) {};
+ ~HostDiskUsage() { delete mTotal; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "mB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ com::Utf8Str mDiskName;
+ SubMetric *mTotal;
+ };
+
+ class HostDiskLoadRaw : public BaseMetric
+ {
+ public:
+ HostDiskLoadRaw(CollectorHAL *hal, ComPtr<IUnknown> object, com::Utf8Str name, com::Utf8Str diskname, SubMetric *util)
+ : BaseMetric(hal, name, object), mDiskName(diskname), mUtil(util), mDiskPrev(0), mTotalPrev(0) {};
+ ~HostDiskLoadRaw() { delete mUtil; };
+
+ void init(ULONG period, ULONG length);
+
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "%"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return PM_DISK_LOAD_MULTIPLIER; };
+ ULONG getScale() { return PM_DISK_LOAD_MULTIPLIER / 100; }
+
+ private:
+ com::Utf8Str mDiskName;
+ SubMetric *mUtil;
+ uint64_t mDiskPrev;
+ uint64_t mTotalPrev;
+ };
+
+
#ifndef VBOX_COLLECTOR_TEST_CASE
class HostRamVmm : public BaseMetric
{
@@ -573,6 +715,52 @@ namespace pm
#ifndef VBOX_COLLECTOR_TEST_CASE
+ typedef std::list<ComObjPtr<Medium> > MediaList;
+ class MachineDiskUsage : public BaseMetric
+ {
+ public:
+ MachineDiskUsage(CollectorHAL *hal, ComPtr<IUnknown> object, MediaList &disks, SubMetric *used)
+ : BaseMetric(hal, "Disk/Usage", object), mDisks(disks), mUsed(used) {};
+ ~MachineDiskUsage() { delete mUsed; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ const char *getUnit() { return "mB"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ MediaList mDisks;
+ SubMetric *mUsed;
+ };
+
+ /*
+ * Although MachineNetRate is measured for VM, not for the guest, it is
+ * derived from BaseGuestMetric since it uses the same mechanism for
+ * data collection -- values get pushed by Guest class along with other
+ * guest statistics.
+ */
+ class MachineNetRate : public BaseGuestMetric
+ {
+ public:
+ MachineNetRate(CollectorGuest *cguest, ComPtr<IUnknown> object, SubMetric *rx, SubMetric *tx)
+ : BaseGuestMetric(cguest, "Net/Rate", object), mRx(rx), mTx(tx) {};
+ ~MachineNetRate() { delete mRx; delete mTx; };
+
+ void init(ULONG period, ULONG length);
+ void preCollect(CollectorHints& hints, uint64_t iTick);
+ void collect();
+ int enable();
+ int disable();
+ const char *getUnit() { return "B/s"; };
+ ULONG getMinValue() { return 0; };
+ ULONG getMaxValue() { return INT32_MAX; };
+ ULONG getScale() { return 1; }
+ private:
+ SubMetric *mRx, *mTx;
+ };
+
class GuestCpuLoad : public BaseGuestMetric
{
public:
@@ -692,6 +880,7 @@ namespace pm
public:
Filter(ComSafeArrayIn(IN_BSTR, metricNames),
ComSafeArrayIn(IUnknown * , objects));
+ Filter(const com::Utf8Str name, const ComPtr<IUnknown> &aObject);
static bool patternMatch(const char *pszPat, const char *pszName,
bool fSeenColon = false);
bool match(const ComPtr<IUnknown> object, const RTCString &name) const;
diff --git a/src/VBox/Main/include/PerformanceImpl.h b/src/VBox/Main/include/PerformanceImpl.h
index 69851718c..26e83b4df 100644
--- a/src/VBox/Main/include/PerformanceImpl.h
+++ b/src/VBox/Main/include/PerformanceImpl.h
@@ -173,8 +173,8 @@ public:
void registerBaseMetric (pm::BaseMetric *baseMetric);
void registerMetric (pm::Metric *metric);
- void unregisterBaseMetricsFor (const ComPtr<IUnknown> &object);
- void unregisterMetricsFor (const ComPtr<IUnknown> &object);
+ void unregisterBaseMetricsFor (const ComPtr<IUnknown> &object, const Utf8Str name = "*");
+ void unregisterMetricsFor (const ComPtr<IUnknown> &object, const Utf8Str name = "*");
void registerGuest(pm::CollectorGuest* pGuest);
void unregisterGuest(pm::CollectorGuest* pGuest);
diff --git a/src/VBox/Main/include/ProgressProxyImpl.h b/src/VBox/Main/include/ProgressProxyImpl.h
index 8e1715ca0..87ebd7089 100644
--- a/src/VBox/Main/include/ProgressProxyImpl.h
+++ b/src/VBox/Main/include/ProgressProxyImpl.h
@@ -27,7 +27,6 @@
* attributes to a different IProgress object for a period of time.
*/
class ATL_NO_VTABLE ProgressProxy :
- //public com::SupportErrorInfoDerived<Progress, ProgressProxy, IProgress>,
public Progress
{
public:
@@ -93,9 +92,6 @@ public:
const char *aText, ...);
bool setOtherProgressObject(IProgress *pOtherProgress);
- /** For com::SupportErrorInfoImpl. */
- static const char *ComponentName() { return "ProgressProxy"; }
-
protected:
void clearOtherProgressObjectInternal(bool fEarly);
void copyProgressInfo(IProgress *pOtherProgress, bool fEarly);
diff --git a/src/VBox/Main/include/SerialPortImpl.h b/src/VBox/Main/include/SerialPortImpl.h
index 1ecfa939b..9826f705a 100644
--- a/src/VBox/Main/include/SerialPortImpl.h
+++ b/src/VBox/Main/include/SerialPortImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -92,5 +92,5 @@ private:
Data *m;
};
-#endif // ____H_FLOPPYDRIVEIMPL
+#endif // ____H_SERIALPORTIMPL
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/include/SessionImpl.h b/src/VBox/Main/include/SessionImpl.h
index 96a78c445..dd93411a8 100644
--- a/src/VBox/Main/include/SessionImpl.h
+++ b/src/VBox/Main/include/SessionImpl.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -80,7 +80,7 @@ public:
// IInternalSessionControl methods
STDMETHOD(GetPID)(ULONG *aPid);
STDMETHOD(GetRemoteConsole)(IConsole **aConsole);
- STDMETHOD(AssignMachine)(IMachine *aMachine);
+ STDMETHOD(AssignMachine)(IMachine *aMachine, LockType_T aLockType);
STDMETHOD(AssignRemoteMachine)(IMachine *aMachine, IConsole *aConsole);
STDMETHOD(UpdateMachineState)(MachineState_T aMachineState);
STDMETHOD(Uninitialize)();
@@ -94,6 +94,8 @@ public:
STDMETHOD(OnVRDEServerChange)(BOOL aRestart);
STDMETHOD(OnUSBControllerChange)();
STDMETHOD(OnSharedFolderChange)(BOOL aGlobal);
+ STDMETHOD(OnClipboardModeChange)(ClipboardMode_T aClipboardMode);
+ STDMETHOD(OnDragAndDropModeChange)(DragAndDropMode_T aDragAndDropMode);
STDMETHOD(OnUSBDeviceAttach)(IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError, ULONG aMaskedIfs);
STDMETHOD(OnUSBDeviceDetach)(IN_BSTR aId, IVirtualBoxErrorInfo *aError);
STDMETHOD(OnShowWindow)(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId);
diff --git a/src/VBox/Main/include/SnapshotImpl.h b/src/VBox/Main/include/SnapshotImpl.h
index 6310b3d03..1e94e5ea9 100644
--- a/src/VBox/Main/include/SnapshotImpl.h
+++ b/src/VBox/Main/include/SnapshotImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -43,7 +43,7 @@ public:
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(Snapshot)
- VBOX_DEFAULT_INTERFACE_ENTRIES (ISnapshot)
+ VBOX_DEFAULT_INTERFACE_ENTRIES (ISnapshot)
END_COM_MAP()
Snapshot()
@@ -70,16 +70,16 @@ public:
void deparent();
// ISnapshot properties
- STDMETHOD(COMGETTER(Id)) (BSTR *aId);
- STDMETHOD(COMGETTER(Name)) (BSTR *aName);
- STDMETHOD(COMSETTER(Name)) (IN_BSTR aName);
- STDMETHOD(COMGETTER(Description)) (BSTR *aDescription);
- STDMETHOD(COMSETTER(Description)) (IN_BSTR aDescription);
- STDMETHOD(COMGETTER(TimeStamp)) (LONG64 *aTimeStamp);
- STDMETHOD(COMGETTER(Online)) (BOOL *aOnline);
- STDMETHOD(COMGETTER(Machine)) (IMachine **aMachine);
- STDMETHOD(COMGETTER(Parent)) (ISnapshot **aParent);
- STDMETHOD(COMGETTER(Children)) (ComSafeArrayOut (ISnapshot *, aChildren));
+ STDMETHOD(COMGETTER(Id))(BSTR *aId);
+ STDMETHOD(COMGETTER(Name))(BSTR *aName);
+ STDMETHOD(COMSETTER(Name))(IN_BSTR aName);
+ STDMETHOD(COMGETTER(Description))(BSTR *aDescription);
+ STDMETHOD(COMSETTER(Description))(IN_BSTR aDescription);
+ STDMETHOD(COMGETTER(TimeStamp))(LONG64 *aTimeStamp);
+ STDMETHOD(COMGETTER(Online))(BOOL *aOnline);
+ STDMETHOD(COMGETTER(Machine))(IMachine **aMachine);
+ STDMETHOD(COMGETTER(Parent))(ISnapshot **aParent);
+ STDMETHOD(COMGETTER(Children))(ComSafeArrayOut(ISnapshot *, aChildren));
// ISnapshot methods
STDMETHOD(GetChildrenCount)(ULONG* count);
diff --git a/src/VBox/Main/include/StorageControllerImpl.h b/src/VBox/Main/include/StorageControllerImpl.h
index abf130509..98e8d473f 100644
--- a/src/VBox/Main/include/StorageControllerImpl.h
+++ b/src/VBox/Main/include/StorageControllerImpl.h
@@ -73,10 +73,6 @@ public:
STDMETHOD(COMSETTER(UseHostIOCache)) (BOOL fUseHostIOCache);
STDMETHOD(COMGETTER(Bootable)) (BOOL *fBootable);
- // StorageController methods
- STDMETHOD(GetIDEEmulationPort) (LONG DevicePosition, LONG *aPortNumber);
- STDMETHOD(SetIDEEmulationPort) (LONG DevicePosition, LONG aPortNumber);
-
// public methods only for internal purposes
const Utf8Str &getName() const;
@@ -92,6 +88,8 @@ public:
void rollback();
void commit();
+ HRESULT getIDEEmulationPort (LONG DevicePosition, LONG *aPortNumber);
+ HRESULT setIDEEmulationPort (LONG DevicePosition, LONG aPortNumber);
// public methods for internal purposes only
// (ensure there is a caller and a read lock before calling them!)
diff --git a/src/VBox/Main/include/SystemPropertiesImpl.h b/src/VBox/Main/include/SystemPropertiesImpl.h
index 55a06eefa..e910b9823 100644
--- a/src/VBox/Main/include/SystemPropertiesImpl.h
+++ b/src/VBox/Main/include/SystemPropertiesImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -45,7 +45,7 @@ public:
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(SystemProperties)
- VBOX_DEFAULT_INTERFACE_ENTRIES (ISystemProperties)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(ISystemProperties)
END_COM_MAP()
DECLARE_EMPTY_CTOR_DTOR(SystemProperties)
@@ -91,6 +91,10 @@ public:
STDMETHOD(COMGETTER(LogHistoryCount))(ULONG *count);
STDMETHOD(COMSETTER(LogHistoryCount))(ULONG count);
STDMETHOD(COMGETTER(DefaultAudioDriver))(AudioDriverType_T *aAudioDriver);
+ STDMETHOD(COMGETTER(AutostartDatabasePath))(BSTR *aAutostartDbPath);
+ STDMETHOD(COMSETTER(AutostartDatabasePath))(IN_BSTR aAutostartDbPath);
+ STDMETHOD(COMGETTER(DefaultAdditionsISO))(BSTR *aDefaultAdditionsISO);
+ STDMETHOD(COMSETTER(DefaultAdditionsISO))(IN_BSTR aDefaultAdditionsISO);
STDMETHOD(GetMaxNetworkAdapters)(ChipsetType_T aChipset, ULONG *aMaxInstances);
STDMETHOD(GetMaxNetworkAdaptersOfType)(ChipsetType_T aChipset, NetworkAttachmentType_T aType, ULONG *aMaxInstances);
@@ -123,6 +127,8 @@ private:
HRESULT setVRDEAuthLibrary(const Utf8Str &aPath);
HRESULT setWebServiceAuthLibrary(const Utf8Str &aPath);
HRESULT setDefaultVRDEExtPack(const Utf8Str &aPath);
+ HRESULT setAutostartDatabasePath(const Utf8Str &aPath);
+ HRESULT setDefaultAdditionsISO(const Utf8Str &aPath);
VirtualBox * const mParent;
diff --git a/src/VBox/Main/include/USBControllerImpl.h b/src/VBox/Main/include/USBControllerImpl.h
index 19c97a3e0..63ba58f2d 100644
--- a/src/VBox/Main/include/USBControllerImpl.h
+++ b/src/VBox/Main/include/USBControllerImpl.h
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -37,38 +37,38 @@ class ATL_NO_VTABLE USBController :
public:
VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(USBController, IUSBController)
- DECLARE_NOT_AGGREGATABLE (USBController)
+ DECLARE_NOT_AGGREGATABLE(USBController)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(USBController)
- VBOX_DEFAULT_INTERFACE_ENTRIES (IUSBController)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IUSBController)
END_COM_MAP()
- DECLARE_EMPTY_CTOR_DTOR (USBController)
+ DECLARE_EMPTY_CTOR_DTOR(USBController)
HRESULT FinalConstruct();
void FinalRelease();
// public initializer/uninitializer for internal purposes only
- HRESULT init (Machine *aParent);
- HRESULT init (Machine *aParent, USBController *aThat);
- HRESULT initCopy (Machine *aParent, USBController *aThat);
+ HRESULT init(Machine *aParent);
+ HRESULT init(Machine *aParent, USBController *aThat);
+ HRESULT initCopy(Machine *aParent, USBController *aThat);
void uninit();
// IUSBController properties
- STDMETHOD(COMGETTER(Enabled)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(Enabled)) (BOOL aEnabled);
- STDMETHOD(COMGETTER(EnabledEhci)) (BOOL *aEnabled);
- STDMETHOD(COMSETTER(EnabledEhci)) (BOOL aEnabled);
- STDMETHOD(COMGETTER(ProxyAvailable)) (BOOL *aEnabled);
- STDMETHOD(COMGETTER(USBStandard)) (USHORT *aUSBStandard);
- STDMETHOD(COMGETTER(DeviceFilters)) (ComSafeArrayOut (IUSBDeviceFilter *, aDevicesFilters));
+ STDMETHOD(COMGETTER(Enabled))(BOOL *aEnabled);
+ STDMETHOD(COMSETTER(Enabled))(BOOL aEnabled);
+ STDMETHOD(COMGETTER(EnabledEHCI))(BOOL *aEnabled);
+ STDMETHOD(COMSETTER(EnabledEHCI))(BOOL aEnabled);
+ STDMETHOD(COMGETTER(ProxyAvailable))(BOOL *aEnabled);
+ STDMETHOD(COMGETTER(USBStandard))(USHORT *aUSBStandard);
+ STDMETHOD(COMGETTER(DeviceFilters))(ComSafeArrayOut(IUSBDeviceFilter *, aDevicesFilters));
// IUSBController methods
- STDMETHOD(CreateDeviceFilter) (IN_BSTR aName, IUSBDeviceFilter **aFilter);
- STDMETHOD(InsertDeviceFilter) (ULONG aPosition, IUSBDeviceFilter *aFilter);
- STDMETHOD(RemoveDeviceFilter) (ULONG aPosition, IUSBDeviceFilter **aFilter);
+ STDMETHOD(CreateDeviceFilter)(IN_BSTR aName, IUSBDeviceFilter **aFilter);
+ STDMETHOD(InsertDeviceFilter)(ULONG aPosition, IUSBDeviceFilter *aFilter);
+ STDMETHOD(RemoveDeviceFilter)(ULONG aPosition, IUSBDeviceFilter **aFilter);
// public methods only for internal purposes
@@ -77,16 +77,16 @@ public:
void rollback();
void commit();
- void copyFrom (USBController *aThat);
+ void copyFrom(USBController *aThat);
#ifdef VBOX_WITH_USB
- HRESULT onDeviceFilterChange (USBDeviceFilter *aFilter,
- BOOL aActiveChanged = FALSE);
+ HRESULT onDeviceFilterChange(USBDeviceFilter *aFilter,
+ BOOL aActiveChanged = FALSE);
- bool hasMatchingFilter (const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs);
- bool hasMatchingFilter (IUSBDevice *aUSBDevice, ULONG *aMaskedIfs);
+ bool hasMatchingFilter(const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs);
+ bool hasMatchingFilter(IUSBDevice *aUSBDevice, ULONG *aMaskedIfs);
- HRESULT notifyProxy (bool aInsertFilters);
+ HRESULT notifyProxy(bool aInsertFilters);
#endif /* VBOX_WITH_USB */
// public methods for internal purposes only
diff --git a/src/VBox/Main/include/USBProxyService.h b/src/VBox/Main/include/USBProxyService.h
index 1dad12d6f..35099c816 100644
--- a/src/VBox/Main/include/USBProxyService.h
+++ b/src/VBox/Main/include/USBProxyService.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -78,6 +78,7 @@ public:
* @{ */
virtual int captureDevice(HostUSBDevice *aDevice);
virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
+ /** @todo unused */
virtual void detachingDevice(HostUSBDevice *aDevice);
virtual int releaseDevice(HostUSBDevice *aDevice);
virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
@@ -159,6 +160,7 @@ public:
virtual int captureDevice(HostUSBDevice *aDevice);
virtual void captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
+ /** @todo unused */
virtual void detachingDevice(HostUSBDevice *aDevice);
virtual int releaseDevice(HostUSBDevice *aDevice);
virtual void releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess);
diff --git a/src/VBox/Main/include/VirtualBoxBase.h b/src/VBox/Main/include/VirtualBoxBase.h
index f16f48e3e..bde071c09 100644
--- a/src/VBox/Main/include/VirtualBoxBase.h
+++ b/src/VBox/Main/include/VirtualBoxBase.h
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -36,6 +36,11 @@ namespace xml
class File;
}
+namespace com
+{
+class ErrorInfo;
+}
+
using namespace com;
using namespace util;
@@ -46,8 +51,8 @@ class VirtualBox;
class Machine;
class Medium;
class Host;
-typedef std::list< ComObjPtr<Medium> > MediaList;
-typedef std::list<Guid> GuidList;
+typedef std::list<ComObjPtr<Medium> > MediaList;
+typedef std::list<Utf8Str> StringsList;
////////////////////////////////////////////////////////////////////////////////
//
@@ -55,7 +60,7 @@ typedef std::list<Guid> GuidList;
//
////////////////////////////////////////////////////////////////////////////////
-#if !defined (VBOX_WITH_XPCOM)
+#if !defined(VBOX_WITH_XPCOM)
#include <atlcom.h>
@@ -131,7 +136,7 @@ public:
CComPtr<IUnknown> m_spObj;
};
-#endif /* !defined (VBOX_WITH_XPCOM) */
+#endif /* !defined(VBOX_WITH_XPCOM) */
////////////////////////////////////////////////////////////////////////////////
//
@@ -141,17 +146,17 @@ public:
/**
* Special version of the Assert macro to be used within VirtualBoxBase
- * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
+ * subclasses.
*
* In the debug build, this macro is equivalent to Assert.
* In the release build, this macro uses |setError(E_FAIL, ...)| to set the
* error info from the asserted expression.
*
- * @see VirtualBoxSupportErrorInfoImpl::setError
+ * @see VirtualBoxBase::setError
*
* @param expr Expression which should be true.
*/
-#if defined (DEBUG)
+#if defined(DEBUG)
#define ComAssert(expr) Assert(expr)
#else
#define ComAssert(expr) \
@@ -165,16 +170,16 @@ public:
/**
* Special version of the AssertFailed macro to be used within VirtualBoxBase
- * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
+ * subclasses.
*
* In the debug build, this macro is equivalent to AssertFailed.
* In the release build, this macro uses |setError(E_FAIL, ...)| to set the
* error info from the asserted expression.
*
- * @see VirtualBoxSupportErrorInfoImpl::setError
+ * @see VirtualBoxBase::setError
*
*/
-#if defined (DEBUG)
+#if defined(DEBUG)
#define ComAssertFailed() AssertFailed()
#else
#define ComAssertFailed() \
@@ -187,14 +192,14 @@ public:
/**
* Special version of the AssertMsg macro to be used within VirtualBoxBase
- * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
+ * subclasses.
*
* See ComAssert for more info.
*
* @param expr Expression which should be true.
* @param a printf argument list (in parenthesis).
*/
-#if defined (DEBUG)
+#if defined(DEBUG)
#define ComAssertMsg(expr, a) AssertMsg(expr, a)
#else
#define ComAssertMsg(expr, a) \
@@ -208,13 +213,13 @@ public:
/**
* Special version of the AssertRC macro to be used within VirtualBoxBase
- * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
+ * subclasses.
*
* See ComAssert for more info.
*
* @param vrc VBox status code.
*/
-#if defined (DEBUG)
+#if defined(DEBUG)
#define ComAssertRC(vrc) AssertRC(vrc)
#else
#define ComAssertRC(vrc) ComAssertMsgRC(vrc, ("%Rra", vrc))
@@ -222,14 +227,14 @@ public:
/**
* Special version of the AssertMsgRC macro to be used within VirtualBoxBase
- * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
+ * subclasses.
*
* See ComAssert for more info.
*
* @param vrc VBox status code.
* @param msg printf argument list (in parenthesis).
*/
-#if defined (DEBUG)
+#if defined(DEBUG)
#define ComAssertMsgRC(vrc, msg) AssertMsgRC(vrc, msg)
#else
#define ComAssertMsgRC(vrc, msg) ComAssertMsg(RT_SUCCESS(vrc), msg)
@@ -237,13 +242,13 @@ public:
/**
* Special version of the AssertComRC macro to be used within VirtualBoxBase
- * subclasses that also inherit the VirtualBoxSupportErrorInfoImpl template.
+ * subclasses.
*
* See ComAssert for more info.
*
* @param rc COM result code
*/
-#if defined (DEBUG)
+#if defined(DEBUG)
#define ComAssertComRC(rc) AssertComRC(rc)
#else
#define ComAssertComRC(rc) ComAssertMsg(SUCCEEDED(rc), ("COM RC = %Rhrc (0x%08X)", (rc), (rc)))
@@ -267,7 +272,7 @@ public:
do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (rc); } while (0)
/** Special version of ComAssert that returns ret */
#define ComAssertFailedRet(ret) \
- if (1) { ComAssertFailed(); { return (ret); } } else do {} while (0)
+ do { ComAssertFailed(); return (ret); } while (0)
/** Special version of ComAssert that evaluates eval and breaks if expr fails */
@@ -275,39 +280,39 @@ public:
if (1) { ComAssert(expr); if (!(expr)) { eval; break; } } else do {} while (0)
/** Special version of ComAssertMsg that evaluates eval and breaks if expr fails */
#define ComAssertMsgBreak(expr, a, eval) \
- if (1) { ComAssertMsg(expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
+ if (1) { ComAssertMsg(expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
/** Special version of ComAssertRC that evaluates eval and breaks if vrc does not succeed */
#define ComAssertRCBreak(vrc, eval) \
- if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { eval; break; } } else do {} while (0)
+ if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { eval; break; } } else do {} while (0)
/** Special version of ComAssertFailed that evaluates eval and breaks */
#define ComAssertFailedBreak(eval) \
- if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0)
+ if (1) { ComAssertFailed(); { eval; break; } } else do {} while (0)
/** Special version of ComAssertMsgFailed that evaluates eval and breaks */
#define ComAssertMsgFailedBreak(msg, eval) \
- if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0)
+ if (1) { ComAssertMsgFailed (msg); { eval; break; } } else do {} while (0)
/** Special version of ComAssertComRC that evaluates eval and breaks if rc does not succeed */
#define ComAssertComRCBreak(rc, eval) \
- if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { eval; break; } } else do {} while (0)
+ if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { eval; break; } } else do {} while (0)
/** Special version of ComAssertComRC that just breaks if rc does not succeed */
#define ComAssertComRCBreakRC(rc) \
- if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { break; } } else do {} while (0)
+ if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { break; } } else do {} while (0)
/** Special version of ComAssert that evaluates eval and throws it if expr fails */
#define ComAssertThrow(expr, eval) \
- if (1) { ComAssert(expr); if (!(expr)) { throw (eval); } } else do {} while (0)
+ do { ComAssert(expr); if (!(expr)) { throw (eval); } } while (0)
/** Special version of ComAssertRC that evaluates eval and throws it if vrc does not succeed */
#define ComAssertRCThrow(vrc, eval) \
- if (1) { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { throw (eval); } } else do {} while (0)
+ do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { throw (eval); } } while (0)
/** Special version of ComAssertComRC that evaluates eval and throws it if rc does not succeed */
#define ComAssertComRCThrow(rc, eval) \
- if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw (eval); } } else do {} while (0)
+ do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw (eval); } } while (0)
/** Special version of ComAssertComRC that just throws rc if rc does not succeed */
#define ComAssertComRCThrowRC(rc) \
- if (1) { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw rc; } } else do {} while (0)
+ do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw rc; } } while (0)
/** Special version of ComAssert that throws eval */
#define ComAssertFailedThrow(eval) \
- if (1) { ComAssertFailed(); { throw (eval); } } else do {} while (0)
+ do { ComAssertFailed(); { throw (eval); } } while (0)
////////////////////////////////////////////////////////////////////////////////
@@ -345,15 +350,26 @@ public:
} while (0)
/**
- * Checks that the string argument is not a NULL or empty string and returns
- * E_INVALIDARG + extended error info on failure.
- * @param arg Input string argument (BSTR etc.).
+ * Checks that a string input argument is valid (not NULL or obviously invalid
+ * pointer), returning E_INVALIDARG + extended error info if invalid.
+ * @param a_bstrIn Input string argument (IN_BSTR).
*/
-#define CheckComArgStrNotEmptyOrNull(arg) \
+#define CheckComArgStr(a_bstrIn) \
do { \
- if (RT_UNLIKELY((arg) == NULL || *(arg) == '\0')) \
- return setError(E_INVALIDARG, \
- tr("Argument %s is empty or NULL"), #arg); \
+ IN_BSTR const bstrInCheck = (a_bstrIn); /* type check */ \
+ if (RT_UNLIKELY(!RT_VALID_PTR(bstrInCheck))) \
+ return setError(E_INVALIDARG, tr("Argument %s is an invalid pointer"), #a_bstrIn); \
+ } while (0)
+/**
+ * Checks that the string argument is not a NULL, a invalid pointer or an empty
+ * string, returning E_INVALIDARG + extended error info on failure.
+ * @param a_bstrIn Input string argument (BSTR etc.).
+ */
+#define CheckComArgStrNotEmptyOrNull(a_bstrIn) \
+ do { \
+ IN_BSTR const bstrInCheck = (a_bstrIn); /* type check */ \
+ if (RT_UNLIKELY(!RT_VALID_PTR(bstrInCheck) || *(bstrInCheck) == '\0')) \
+ return setError(E_INVALIDARG, tr("Argument %s is empty or an invalid pointer"), #a_bstrIn); \
} while (0)
/**
@@ -397,7 +413,7 @@ public:
#define CheckComArgExprMsg(arg, expr, msg) \
do { \
if (RT_UNLIKELY(!(expr))) \
- return setError(E_INVALIDARG, tr ("Argument %s %s"), \
+ return setError(E_INVALIDARG, tr("Argument %s %s"), \
#arg, Utf8StrFmt msg .c_str()); \
} while (0)
@@ -411,7 +427,7 @@ public:
if (RT_UNLIKELY(!VALID_PTR(arg))) \
return setError(E_POINTER, \
tr("Output argument %s points to invalid memory location (%p)"), \
- #arg, (void *) (arg)); \
+ #arg, (void *)(arg)); \
} while (0)
/**
@@ -696,7 +712,7 @@ public:
/**
* Adds a limited caller. This method is equivalent to doing
- * <tt>addCaller (aState, true)</tt>, but it is preferred because provides
+ * <tt>addCaller(aState, true)</tt>, but it is preferred because provides
* better self-descriptiveness. See #addCaller() for more info.
*/
HRESULT addLimitedCaller(State *aState = NULL)
@@ -742,15 +758,19 @@ public:
*/
WriteLockHandle *stateLockHandle() { return &mStateLock; }
+ static HRESULT handleUnexpectedExceptions(VirtualBoxBase *const aThis, RT_SRC_POS_DECL);
+
static HRESULT setErrorInternal(HRESULT aResultCode,
const GUID &aIID,
const char *aComponent,
- const Utf8Str &aText,
+ Utf8Str aText,
bool aWarning,
bool aLogIt);
static void clearError(void);
+ HRESULT setError(HRESULT aResultCode);
HRESULT setError(HRESULT aResultCode, const char *pcsz, ...);
+ HRESULT setError(const ErrorInfo &ei);
HRESULT setWarning(HRESULT aResultCode, const char *pcsz, ...);
HRESULT setErrorNoLog(HRESULT aResultCode, const char *pcsz, ...);
@@ -811,7 +831,7 @@ private:
* Dummy macro that is used to shut down Qt's lupdate tool warnings in some
* situations. This macro needs to be present inside (better at the very
* beginning) of the declaration of the class that inherits from
- * VirtualBoxSupportTranslation template, to make lupdate happy.
+ * VirtualBoxTranslatable, to make lupdate happy.
*/
#define Q_OBJECT
@@ -831,7 +851,7 @@ class Shareable
{
public:
- Shareable() : mData (NULL), mIsShared(FALSE) {}
+ Shareable() : mData(NULL), mIsShared(FALSE) {}
~Shareable() { free(); }
void allocate() { attach(new D); }
@@ -925,7 +945,7 @@ class Backupable : public Shareable<D>
{
public:
- Backupable() : Shareable<D> (), mBackupData(NULL) {}
+ Backupable() : Shareable<D>(), mBackupData(NULL) {}
void free()
{
@@ -951,6 +971,8 @@ public:
/**
* Stores the current data pointer in the backup area, allocates new data
* using the copy constructor on current data and makes new data active.
+ *
+ * @deprecated Use backupEx to avoid throwing wild out-of-memory exceptions.
*/
void backup()
{
@@ -964,6 +986,31 @@ public:
}
/**
+ * Stores the current data pointer in the backup area, allocates new data
+ * using the copy constructor on current data and makes new data active.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_FAIL (internal error).
+ */
+ HRESULT backupEx()
+ {
+ AssertMsgReturn(this->mData, ("data must not be NULL"), E_FAIL);
+ if (this->mData && !mBackupData)
+ {
+ try
+ {
+ D *pNewData = new D(*this->mData);
+ mBackupData = this->mData;
+ this->mData = pNewData;
+ }
+ catch (std::bad_alloc &)
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+ return S_OK;
+ }
+
+ /**
* Deletes new data created by #backup() and restores previous data pointer
* stored in the backup area, making it active again.
*/
diff --git a/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h b/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h
index 21f4140b5..bb47dc54d 100644
--- a/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h
+++ b/src/VBox/Main/include/VirtualBoxErrorInfoImpl.h
@@ -93,6 +93,9 @@ public:
const Utf8Str &strText,
IVirtualBoxErrorInfo *aNext = NULL);
+ HRESULT init(const com::ErrorInfo &ei,
+ IVirtualBoxErrorInfo *aNext = NULL);
+
// IVirtualBoxErrorInfo properties
STDMETHOD(COMGETTER(ResultCode))(LONG *aResultCode);
STDMETHOD(COMGETTER(InterfaceID))(BSTR *aIID);
diff --git a/src/VBox/Main/include/VirtualBoxImpl.h b/src/VBox/Main/include/VirtualBoxImpl.h
index c17fc95dc..3bf748a99 100644
--- a/src/VBox/Main/include/VirtualBoxImpl.h
+++ b/src/VBox/Main/include/VirtualBoxImpl.h
@@ -42,8 +42,9 @@ class VirtualBoxCallbackRegistration; /* see VirtualBoxImpl.cpp */
#ifdef VBOX_WITH_EXTPACK
class ExtPackManager;
#endif
+class AutostartDb;
-typedef std::list< ComObjPtr<SessionMachine> > SessionMachinesList;
+typedef std::list<ComObjPtr<SessionMachine> > SessionMachinesList;
#ifdef RT_OS_WINDOWS
class SVCHlpClient;
@@ -66,7 +67,7 @@ class ATL_NO_VTABLE VirtualBox :
public:
- typedef std::list< ComPtr<IInternalSessionControl> > InternalControlList;
+ typedef std::list<ComPtr<IInternalSessionControl> > InternalControlList;
class CallbackEvent;
friend class CallbackEvent;
@@ -100,40 +101,44 @@ public:
void uninit();
/* IVirtualBox properties */
- STDMETHOD(COMGETTER(Version)) (BSTR *aVersion);
- STDMETHOD(COMGETTER(Revision)) (ULONG *aRevision);
- STDMETHOD(COMGETTER(PackageType)) (BSTR *aPackageType);
- STDMETHOD(COMGETTER(APIVersion)) (BSTR *aAPIVersion);
- STDMETHOD(COMGETTER(HomeFolder)) (BSTR *aHomeFolder);
- STDMETHOD(COMGETTER(SettingsFilePath)) (BSTR *aSettingsFilePath);
- STDMETHOD(COMGETTER(Host)) (IHost **aHost);
- STDMETHOD(COMGETTER(SystemProperties)) (ISystemProperties **aSystemProperties);
- STDMETHOD(COMGETTER(Machines)) (ComSafeArrayOut(IMachine *, aMachines));
- STDMETHOD(COMGETTER(HardDisks)) (ComSafeArrayOut(IMedium *, aHardDisks));
- STDMETHOD(COMGETTER(DVDImages)) (ComSafeArrayOut(IMedium *, aDVDImages));
- STDMETHOD(COMGETTER(FloppyImages)) (ComSafeArrayOut(IMedium *, aFloppyImages));
- STDMETHOD(COMGETTER(ProgressOperations)) (ComSafeArrayOut(IProgress *, aOperations));
- STDMETHOD(COMGETTER(GuestOSTypes)) (ComSafeArrayOut(IGuestOSType *, aGuestOSTypes));
- STDMETHOD(COMGETTER(SharedFolders)) (ComSafeArrayOut(ISharedFolder *, aSharedFolders));
- STDMETHOD(COMGETTER(PerformanceCollector)) (IPerformanceCollector **aPerformanceCollector);
- STDMETHOD(COMGETTER(DHCPServers)) (ComSafeArrayOut(IDHCPServer *, aDHCPServers));
- STDMETHOD(COMGETTER(EventSource)) (IEventSource ** aEventSource);
- STDMETHOD(COMGETTER(ExtensionPackManager)) (IExtPackManager **aExtPackManager);
- STDMETHOD(COMGETTER(InternalNetworks)) (ComSafeArrayOut(BSTR, aInternalNetworks));
- STDMETHOD(COMGETTER(GenericNetworkDrivers)) (ComSafeArrayOut(BSTR, aGenericNetworkDrivers));
+ STDMETHOD(COMGETTER(Version))(BSTR *aVersion);
+ STDMETHOD(COMGETTER(VersionNormalized))(BSTR *aVersionNormalized);
+ STDMETHOD(COMGETTER(Revision))(ULONG *aRevision);
+ STDMETHOD(COMGETTER(PackageType))(BSTR *aPackageType);
+ STDMETHOD(COMGETTER(APIVersion))(BSTR *aAPIVersion);
+ STDMETHOD(COMGETTER(HomeFolder))(BSTR *aHomeFolder);
+ STDMETHOD(COMGETTER(SettingsFilePath))(BSTR *aSettingsFilePath);
+ STDMETHOD(COMGETTER(Host))(IHost **aHost);
+ STDMETHOD(COMGETTER(SystemProperties))(ISystemProperties **aSystemProperties);
+ STDMETHOD(COMGETTER(Machines))(ComSafeArrayOut(IMachine *, aMachines));
+ STDMETHOD(COMGETTER(MachineGroups))(ComSafeArrayOut(BSTR, aMachineGroups));
+ STDMETHOD(COMGETTER(HardDisks))(ComSafeArrayOut(IMedium *, aHardDisks));
+ STDMETHOD(COMGETTER(DVDImages))(ComSafeArrayOut(IMedium *, aDVDImages));
+ STDMETHOD(COMGETTER(FloppyImages))(ComSafeArrayOut(IMedium *, aFloppyImages));
+ STDMETHOD(COMGETTER(ProgressOperations))(ComSafeArrayOut(IProgress *, aOperations));
+ STDMETHOD(COMGETTER(GuestOSTypes))(ComSafeArrayOut(IGuestOSType *, aGuestOSTypes));
+ STDMETHOD(COMGETTER(SharedFolders))(ComSafeArrayOut(ISharedFolder *, aSharedFolders));
+ STDMETHOD(COMGETTER(PerformanceCollector))(IPerformanceCollector **aPerformanceCollector);
+ STDMETHOD(COMGETTER(DHCPServers))(ComSafeArrayOut(IDHCPServer *, aDHCPServers));
+ STDMETHOD(COMGETTER(EventSource))(IEventSource ** aEventSource);
+ STDMETHOD(COMGETTER(ExtensionPackManager))(IExtPackManager **aExtPackManager);
+ STDMETHOD(COMGETTER(InternalNetworks))(ComSafeArrayOut(BSTR, aInternalNetworks));
+ STDMETHOD(COMGETTER(GenericNetworkDrivers))(ComSafeArrayOut(BSTR, aGenericNetworkDrivers));
/* IVirtualBox methods */
- STDMETHOD(ComposeMachineFilename) (IN_BSTR aName, IN_BSTR aBaseFolder, BSTR *aFilename);
- STDMETHOD(CreateMachine) (IN_BSTR aSettingsFile,
- IN_BSTR aName,
- IN_BSTR aOsTypeId,
- IN_BSTR aId,
- BOOL forceOverwrite,
- IMachine **aMachine);
- STDMETHOD(OpenMachine) (IN_BSTR aSettingsFile, IMachine **aMachine);
- STDMETHOD(RegisterMachine) (IMachine *aMachine);
- STDMETHOD(FindMachine) (IN_BSTR aNameOrId, IMachine **aMachine);
- STDMETHOD(CreateAppliance) (IAppliance **anAppliance);
+ STDMETHOD(ComposeMachineFilename)(IN_BSTR aName, IN_BSTR aGroup, IN_BSTR aCreateFlags, IN_BSTR aBaseFolder, BSTR *aFilename);
+ STDMETHOD(CreateMachine)(IN_BSTR aSettingsFile,
+ IN_BSTR aName,
+ ComSafeArrayIn(IN_BSTR, aGroups),
+ IN_BSTR aOsTypeId,
+ IN_BSTR aCreateFlags,
+ IMachine **aMachine);
+ STDMETHOD(OpenMachine)(IN_BSTR aSettingsFile, IMachine **aMachine);
+ STDMETHOD(RegisterMachine)(IMachine *aMachine);
+ STDMETHOD(FindMachine)(IN_BSTR aNameOrId, IMachine **aMachine);
+ STDMETHOD(GetMachinesByGroups)(ComSafeArrayIn(IN_BSTR, aGroups), ComSafeArrayOut(IMachine *, aMachines));
+ STDMETHOD(GetMachineStates)(ComSafeArrayIn(IMachine *, aMachines), ComSafeArrayOut(MachineState_T, aStates));
+ STDMETHOD(CreateAppliance)(IAppliance **anAppliance);
STDMETHOD(CreateHardDisk)(IN_BSTR aFormat,
IN_BSTR aLocation,
@@ -143,20 +148,18 @@ public:
AccessMode_T accessMode,
BOOL fForceNewUuid,
IMedium **aMedium);
- STDMETHOD(FindMedium)(IN_BSTR aLocation,
- DeviceType_T deviceType,
- IMedium **aMedium);
-
- STDMETHOD(GetGuestOSType) (IN_BSTR aId, IGuestOSType **aType);
- STDMETHOD(CreateSharedFolder) (IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable, BOOL aAutoMount);
- STDMETHOD(RemoveSharedFolder) (IN_BSTR aName);
- STDMETHOD(GetExtraDataKeys) (ComSafeArrayOut(BSTR, aKeys));
- STDMETHOD(GetExtraData) (IN_BSTR aKey, BSTR *aValue);
- STDMETHOD(SetExtraData) (IN_BSTR aKey, IN_BSTR aValue);
- STDMETHOD(CreateDHCPServer) (IN_BSTR aName, IDHCPServer ** aServer);
- STDMETHOD(FindDHCPServerByNetworkName) (IN_BSTR aName, IDHCPServer ** aServer);
- STDMETHOD(RemoveDHCPServer) (IDHCPServer * aServer);
+ STDMETHOD(GetGuestOSType)(IN_BSTR aId, IGuestOSType **aType);
+ STDMETHOD(CreateSharedFolder)(IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable, BOOL aAutoMount);
+ STDMETHOD(RemoveSharedFolder)(IN_BSTR aName);
+ STDMETHOD(GetExtraDataKeys)(ComSafeArrayOut(BSTR, aKeys));
+ STDMETHOD(GetExtraData)(IN_BSTR aKey, BSTR *aValue);
+ STDMETHOD(SetExtraData)(IN_BSTR aKey, IN_BSTR aValue);
+ STDMETHOD(SetSettingsSecret)(IN_BSTR aKey);
+
+ STDMETHOD(CreateDHCPServer)(IN_BSTR aName, IDHCPServer ** aServer);
+ STDMETHOD(FindDHCPServerByNetworkName)(IN_BSTR aName, IDHCPServer ** aServer);
+ STDMETHOD(RemoveDHCPServer)(IDHCPServer * aServer);
STDMETHOD(CheckFirmwarePresent)(FirmwareType_T aFirmwareType, IN_BSTR aVersion,
BSTR * aUrl, BSTR * aFile, BOOL * aResult);
@@ -181,14 +184,14 @@ public:
HRESULT removeProgress(IN_GUID aId);
#ifdef RT_OS_WINDOWS
- typedef DECLCALLBACKPTR (HRESULT, SVCHelperClientFunc)
+ typedef DECLCALLBACKPTR(HRESULT, SVCHelperClientFunc)
(SVCHlpClient *aClient, Progress *aProgress, void *aUser, int *aVrc);
HRESULT startSVCHelperClient(bool aPrivileged,
SVCHelperClientFunc aFunc,
void *aUser, Progress *aProgress);
#endif
- void addProcessToReap (RTPROCESS pid);
+ void addProcessToReap(RTPROCESS pid);
void updateClientWatcher();
void onMachineStateChange(const Guid &aId, MachineState_T aState);
@@ -217,7 +220,13 @@ public:
HRESULT findMachine(const Guid &aId,
bool fPermitInaccessible,
bool aSetError,
- ComObjPtr<Machine> *machine = NULL);
+ ComObjPtr<Machine> *aMachine = NULL);
+ HRESULT findMachineByName(const Utf8Str &aName,
+ bool aSetError,
+ ComObjPtr<Machine> *aMachine = NULL);
+
+ HRESULT validateMachineGroup(const Utf8Str &aGroup, bool fPrimary);
+ HRESULT convertMachineGroups(ComSafeArrayIn(IN_BSTR, aMachineGroups), StringsList *pllMachineGroups);
HRESULT findHardDiskById(const Guid &id,
bool aSetError,
@@ -239,7 +248,7 @@ public:
HRESULT findGuestOSType(const Bstr &bstrOSType,
GuestOSType*& pGuestOSType);
- const Guid& getGlobalRegistryId() const;
+ const Guid &getGlobalRegistryId() const;
const ComObjPtr<Host>& host() const;
SystemProperties* getSystemProperties() const;
@@ -259,8 +268,8 @@ public:
int calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult);
void copyPathRelativeToConfig(const Utf8Str &strSource, Utf8Str &strTarget);
- HRESULT registerMedium(const ComObjPtr<Medium> &pMedium, ComObjPtr<Medium> *ppMedium, DeviceType_T argType, GuidList *pllRegistriesThatNeedSaving);
- HRESULT unregisterMedium(Medium *pMedium, GuidList *pllRegistriesThatNeedSaving);
+ HRESULT registerMedium(const ComObjPtr<Medium> &pMedium, ComObjPtr<Medium> *ppMedium, DeviceType_T argType);
+ HRESULT unregisterMedium(Medium *pMedium);
void pushMediumToListWithChildren(MediaList &llMedia, Medium *pMedium);
HRESULT unregisterMachineMedia(const Guid &id);
@@ -275,17 +284,23 @@ public:
const Utf8Str &strMachineFolder);
HRESULT saveSettings();
- static void addGuidToListUniquely(GuidList &llRegistriesThatNeedSaving, const Guid &uuid);
- void saveRegistries(const GuidList &llRegistriesThatNeedSaving);
+ void markRegistryModified(const Guid &uuid);
+ void saveModifiedRegistries();
- static HRESULT ensureFilePathExists(const Utf8Str &strFileName, bool fCreate);
+ static const Bstr &getVersionNormalized();
- static HRESULT handleUnexpectedExceptions (RT_SRC_POS_DECL);
+ static HRESULT ensureFilePathExists(const Utf8Str &strFileName, bool fCreate);
const Utf8Str& settingsFilePath();
+ AutostartDb* getAutostartDb() const;
+
RWLockHandle& getMediaTreeLockHandle();
+ int encryptSetting(const Utf8Str &aPlaintext, Utf8Str *aCiphertext);
+ int decryptSetting(Utf8Str *aPlaintext, const Utf8Str &aCiphertext);
+ void storeSettingsKey(const Utf8Str &aKey);
+
private:
static HRESULT setErrorStatic(HRESULT aResultCode,
@@ -306,20 +321,28 @@ private:
HRESULT unregisterDHCPServer(DHCPServer *aDHCPServer,
bool aSaveRegistry = true);
+ int decryptSettings();
+ int decryptMediumSettings(Medium *pMedium);
+ int decryptSettingBytes(uint8_t *aPlaintext, const uint8_t *aCiphertext,
+ size_t aCiphertextSize) const;
+ int encryptSettingBytes(const uint8_t *aPlaintext, uint8_t *aCiphertext,
+ size_t aPlaintextSize, size_t aCiphertextSize) const;
+
struct Data; // opaque data structure, defined in VirtualBoxImpl.cpp
Data *m;
/* static variables (defined in VirtualBoxImpl.cpp) */
static Bstr sVersion;
+ static Bstr sVersionNormalized;
static ULONG sRevision;
static Bstr sPackageType;
static Bstr sAPIVersion;
- static DECLCALLBACK(int) ClientWatcher (RTTHREAD thread, void *pvUser);
- static DECLCALLBACK(int) AsyncEventHandler (RTTHREAD thread, void *pvUser);
+ static DECLCALLBACK(int) ClientWatcher(RTTHREAD thread, void *pvUser);
+ static DECLCALLBACK(int) AsyncEventHandler(RTTHREAD thread, void *pvUser);
#ifdef RT_OS_WINDOWS
- static DECLCALLBACK(int) SVCHelperClientThread (RTTHREAD aThread, void *aUser);
+ static DECLCALLBACK(int) SVCHelperClientThread(RTTHREAD aThread, void *aUser);
#endif
};
diff --git a/src/VBox/Main/include/netif.h b/src/VBox/Main/include/netif.h
index 3942926c5..b1ab8901f 100644
--- a/src/VBox/Main/include/netif.h
+++ b/src/VBox/Main/include/netif.h
@@ -71,6 +71,7 @@ typedef struct NETIFINFO
RTMAC MACAddress;
NETIFTYPE enmMediumType;
NETIFSTATUS enmStatus;
+ uint32_t uSpeedMbits;
RTUUID Uuid;
char szShortName[VBOXNET_MAX_SHORT_NAME];
char szName[1];
@@ -91,6 +92,7 @@ int NetIfRemoveHostOnlyNetworkInterface (VirtualBox *pVbox, IN_GUID aId, IProgre
int NetIfGetConfig(HostNetworkInterface * pIf, NETIFINFO *);
int NetIfGetConfigByName(PNETIFINFO pInfo);
int NetIfDhcpRediscover(VirtualBox *pVbox, HostNetworkInterface * pIf);
+int NetIfAdpCtlOut(const char * pcszName, const char * pcszCmd, char *pszBuffer, size_t cBufSize);
DECLINLINE(Bstr) composeIPv6Address(PRTNETADDRIPV6 aAddrPtr)
{
diff --git a/src/VBox/Main/src-all/DisplayUtils.cpp b/src/VBox/Main/src-all/DisplayUtils.cpp
index 691155d78..efc994f3a 100644
--- a/src/VBox/Main/src-all/DisplayUtils.cpp
+++ b/src/VBox/Main/src-all/DisplayUtils.cpp
@@ -20,6 +20,7 @@
#include <iprt/log.h>
#include <VBox/err.h>
#include <VBox/vmm/ssm.h>
+#include <VBox/VBoxVideo.h>
int readSavedDisplayScreenshot(const Utf8Str &strStateFilePath, uint32_t u32Type, uint8_t **ppu8Data, uint32_t *pcbData, uint32_t *pu32Width, uint32_t *pu32Height)
{
@@ -140,7 +141,9 @@ void freeSavedDisplayScreenshot(uint8_t *pu8Data)
RTMemFree(pu8Data);
}
-int readSavedGuestSize(const Utf8Str &strStateFilePath, uint32_t u32ScreenId, uint32_t *pu32Width, uint32_t *pu32Height)
+int readSavedGuestScreenInfo(const Utf8Str &strStateFilePath, uint32_t u32ScreenId,
+ uint32_t *pu32OriginX, uint32_t *pu32OriginY,
+ uint32_t *pu32Width, uint32_t *pu32Height, uint16_t *pu16Flags)
{
LogFlowFunc(("u32ScreenId = %d [%s]\n", u32ScreenId, strStateFilePath.c_str()));
@@ -151,9 +154,6 @@ int readSavedGuestSize(const Utf8Str &strStateFilePath, uint32_t u32ScreenId, ui
return VERR_NOT_SUPPORTED;
}
- uint32_t u32Width = 0;
- uint32_t u32Height = 0;
-
PSSMHANDLE pSSM;
int vrc = SSMR3Open(strStateFilePath.c_str(), 0 /*fFlags*/, &pSSM);
if (RT_SUCCESS(vrc))
@@ -162,33 +162,51 @@ int readSavedGuestSize(const Utf8Str &strStateFilePath, uint32_t u32ScreenId, ui
vrc = SSMR3Seek(pSSM, "DisplayData", 0 /*iInstance*/, &uVersion);
if (RT_SUCCESS(vrc))
{
- /* Only the second version is supported. */
if ( uVersion == sSSMDisplayVer2
|| uVersion == sSSMDisplayVer3)
{
uint32_t cMonitors;
SSMR3GetU32(pSSM, &cMonitors);
if (u32ScreenId > cMonitors)
- vrc = -2;
+ {
+ vrc = VERR_INVALID_PARAMETER;
+ }
else
{
- /* Skip all previous monitors and the first 3 entries. */
- SSMR3Skip(pSSM, u32ScreenId * 5 * sizeof(uint32_t) + 3 * sizeof(uint32_t));
- SSMR3GetU32(pSSM, &u32Width);
- SSMR3GetU32(pSSM, &u32Height);
+ if (uVersion == sSSMDisplayVer2)
+ {
+ /* Skip all previous monitors, each 5 uint32_t, and the first 3 uint32_t entries. */
+ SSMR3Skip(pSSM, u32ScreenId * 5 * sizeof(uint32_t) + 3 * sizeof(uint32_t));
+ SSMR3GetU32(pSSM, pu32Width);
+ SSMR3GetU32(pSSM, pu32Height);
+ *pu32OriginX = 0;
+ *pu32OriginY = 0;
+ *pu16Flags = VBVA_SCREEN_F_ACTIVE;
+ }
+ else
+ {
+ Assert(uVersion == sSSMDisplayVer3);
+ /* Skip all previous monitors, each 8 uint32_t, and the first 3 uint32_t entries. */
+ SSMR3Skip(pSSM, u32ScreenId * 8 * sizeof(uint32_t) + 3 * sizeof(uint32_t));
+ SSMR3GetU32(pSSM, pu32Width);
+ SSMR3GetU32(pSSM, pu32Height);
+ SSMR3GetU32(pSSM, pu32OriginX);
+ SSMR3GetU32(pSSM, pu32OriginY);
+ uint32_t u32Flags = 0;
+ SSMR3GetU32(pSSM, &u32Flags);
+ *pu16Flags = (uint16_t)u32Flags;
+ }
}
}
+ else
+ {
+ vrc = VERR_NOT_SUPPORTED;
+ }
}
SSMR3Close(pSSM);
}
- if (RT_SUCCESS(vrc))
- {
- *pu32Width = u32Width;
- *pu32Height = u32Height;
- }
-
LogFlowFunc(("vrc %Rrc\n", vrc));
return vrc;
}
diff --git a/src/VBox/Main/src-all/EventImpl.cpp b/src/VBox/Main/src-all/EventImpl.cpp
index 131b8d824..03eb7e3c4 100644
--- a/src/VBox/Main/src-all/EventImpl.cpp
+++ b/src/VBox/Main/src-all/EventImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -429,7 +429,7 @@ public:
class EventMapList
{
- EventMapRecord* mHead;
+ EventMapRecord *mHead;
uint32_t mSize;
public:
EventMapList()
@@ -439,12 +439,12 @@ public:
{}
~EventMapList()
{
- EventMapRecord* aCur = mHead;
- while (aCur)
+ EventMapRecord *pCur = mHead;
+ while (pCur)
{
- EventMapRecord* aNext = aCur->mNext;
- aCur->release();
- aCur = aNext;
+ EventMapRecord *pNext = pCur->mNext;
+ pCur->release();
+ pCur = pNext;
}
}
@@ -453,13 +453,13 @@ public:
* that iterators doesn't see newly added listeners, and iteration
* will always complete.
*/
- void add(ListenerRecord* aRec)
+ void add(ListenerRecord *aRec)
{
- EventMapRecord* aNew = new EventMapRecord(aRec);
- aNew->mNext = mHead;
+ EventMapRecord *pNew = new EventMapRecord(aRec);
+ pNew->mNext = mHead;
if (mHead)
- mHead->mPrev = aNew;
- mHead = aNew;
+ mHead->mPrev = pNew;
+ mHead = pNew;
mSize++;
}
@@ -468,21 +468,21 @@ public:
* all consumers release it too. This helps to keep list stable
* enough for iterators to allow long and probably intrusive callbacks.
*/
- void remove(ListenerRecord* aRec)
+ void remove(ListenerRecord *aRec)
{
- EventMapRecord* aCur = mHead;
- while (aCur)
+ EventMapRecord *pCur = mHead;
+ while (pCur)
{
- EventMapRecord* aNext = aCur->mNext;
- if (aCur->ref() == aRec)
+ EventMapRecord* aNext = pCur->mNext;
+ if (pCur->ref() == aRec)
{
- if (aCur == mHead)
+ if (pCur == mHead)
mHead = aNext;
- aCur->kill();
+ pCur->kill();
mSize--;
// break?
}
- aCur = aNext;
+ pCur = aNext;
}
}
@@ -493,62 +493,62 @@ public:
struct iterator
{
- EventMapRecord* mCur;
-
- iterator()
- : mCur(0)
- {}
-
- explicit
- iterator(EventMapRecord* aCur)
- : mCur(aCur)
- {
- // Prevent element removal, till we're at it
- if (mCur)
- mCur->addRef();
- }
-
- ~iterator()
- {
- if (mCur)
- mCur->release();
- }
-
- ListenerRecord*
- operator*() const
- {
- return mCur->ref();
- }
-
- EventMapList::iterator&
- operator++()
- {
- EventMapRecord* aPrev = mCur;
- do {
- mCur = mCur->mNext;
- } while (mCur && !mCur->mAlive);
-
- // now we can safely release previous element
- aPrev->release();
-
- // And grab the new current
- if (mCur)
- mCur->addRef();
-
- return *this;
- }
-
- bool
- operator==(const EventMapList::iterator& aOther) const
- {
- return mCur == aOther.mCur;
- }
-
- bool
- operator!=(const EventMapList::iterator& aOther) const
- {
- return mCur != aOther.mCur;
- }
+ EventMapRecord *mCur;
+
+ iterator()
+ : mCur(0)
+ {}
+
+ explicit
+ iterator(EventMapRecord *aCur)
+ : mCur(aCur)
+ {
+ // Prevent element removal, till we're at it
+ if (mCur)
+ mCur->addRef();
+ }
+
+ ~iterator()
+ {
+ if (mCur)
+ mCur->release();
+ }
+
+ ListenerRecord *
+ operator*() const
+ {
+ return mCur->ref();
+ }
+
+ EventMapList::iterator &
+ operator++()
+ {
+ EventMapRecord *pPrev = mCur;
+ do {
+ mCur = mCur->mNext;
+ } while (mCur && !mCur->mAlive);
+
+ // now we can safely release previous element
+ pPrev->release();
+
+ // And grab the new current
+ if (mCur)
+ mCur->addRef();
+
+ return *this;
+ }
+
+ bool
+ operator==(const EventMapList::iterator& aOther) const
+ {
+ return mCur == aOther.mCur;
+ }
+
+ bool
+ operator!=(const EventMapList::iterator& aOther) const
+ {
+ return mCur != aOther.mCur;
+ }
};
iterator begin()
@@ -802,7 +802,7 @@ HRESULT ListenerRecord::process(IEvent* aEvent,
if (mListener)
{
aAlock.release();
- rc = mListener->HandleEvent(aEvent);
+ rc = mListener->HandleEvent(aEvent);
#ifdef RT_OS_WINDOWS
Assert(rc != RPC_E_WRONG_THREAD);
#endif
@@ -812,8 +812,7 @@ HRESULT ListenerRecord::process(IEvent* aEvent,
eventProcessed(aEvent, pit);
return rc;
}
- else
- return enqueue(aEvent);
+ return enqueue(aEvent);
}
@@ -1031,7 +1030,7 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
hrc = aEvent->COMGETTER(Type)(&evType);
AssertComRCReturn(hrc, hrc);
- EventMapList& listeners = m->mEvMap[(int)evType-FirstEvent];
+ EventMapList &listeners = m->mEvMap[(int)evType - FirstEvent];
/* Anyone interested in this event? */
uint32_t cListeners = listeners.size();
@@ -1050,14 +1049,15 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
// pending events lookup
pit = m->mPendingMap.find(aEvent);
}
- for(EventMapList::iterator it = listeners.begin();
- it != listeners.end(); ++it)
+ for (EventMapList::iterator it = listeners.begin();
+ it != listeners.end();
+ ++it)
{
HRESULT cbRc;
// keep listener record reference, in case someone will remove it while in callback
RecordHolder<ListenerRecord> record(*it);
- /**
+ /*
* We pass lock here to allow modifying ops on EventSource inside callback
* in active mode. Note that we expect list iterator stability as 'alock'
* could be temporary released when calling event handler.
@@ -1068,7 +1068,7 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
* listener was unregistered due to not picking up its event.
* This overlaps with XPCOM specific use of E_ABORT to signal
* death of an active listener, but that's irrelevant here. */
- if (FAILED_DEAD_INTERFACE(cbRc) || (cbRc == E_ABORT))
+ if (FAILED_DEAD_INTERFACE(cbRc) || cbRc == E_ABORT)
{
Listeners::iterator lit = m->mListeners.find(record.obj()->mListener);
if (lit != m->mListeners.end())
diff --git a/src/VBox/Main/src-all/ExtPackManagerImpl.cpp b/src/VBox/Main/src-all/ExtPackManagerImpl.cpp
index 07f7f8947..5b1a69293 100644
--- a/src/VBox/Main/src-all/ExtPackManagerImpl.cpp
+++ b/src/VBox/Main/src-all/ExtPackManagerImpl.cpp
@@ -393,22 +393,22 @@ STDMETHODIMP ExtPackFile::COMGETTER(Version)(BSTR *a_pbstrVersion)
HRESULT hrc = autoCaller.rc();
if (SUCCEEDED(hrc))
{
- /* HACK ALERT: This is for easing backporting to 4.1. The edition stuff
- will be changed into a separate */
- if (m->Desc.strEdition.isEmpty())
- {
- Bstr str(m->Desc.strVersion);
- str.cloneTo(a_pbstrVersion);
- }
- else
- {
- RTCString strHack(m->Desc.strVersion);
- strHack.append('-');
- strHack.append(m->Desc.strEdition);
+ Bstr str(m->Desc.strVersion);
+ str.cloneTo(a_pbstrVersion);
+ }
+ return hrc;
+}
- Bstr str(strHack);
- str.cloneTo(a_pbstrVersion);
- }
+STDMETHODIMP ExtPackFile::COMGETTER(Edition)(BSTR *a_pbstrEdition)
+{
+ CheckComArgOutPointerValid(a_pbstrEdition);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ Bstr str(m->Desc.strEdition);
+ str.cloneTo(a_pbstrEdition);
}
return hrc;
}
@@ -1627,22 +1627,8 @@ STDMETHODIMP ExtPack::COMGETTER(Version)(BSTR *a_pbstrVersion)
HRESULT hrc = autoCaller.rc();
if (SUCCEEDED(hrc))
{
- /* HACK ALERT: This is for easing backporting to 4.1. The edition stuff
- will be changed into a separate */
- if (m->Desc.strEdition.isEmpty())
- {
- Bstr str(m->Desc.strVersion);
- str.cloneTo(a_pbstrVersion);
- }
- else
- {
- RTCString strHack(m->Desc.strVersion);
- strHack.append('-');
- strHack.append(m->Desc.strEdition);
-
- Bstr str(strHack);
- str.cloneTo(a_pbstrVersion);
- }
+ Bstr str(m->Desc.strVersion);
+ str.cloneTo(a_pbstrVersion);
}
return hrc;
}
@@ -1658,6 +1644,20 @@ STDMETHODIMP ExtPack::COMGETTER(Revision)(ULONG *a_puRevision)
return hrc;
}
+STDMETHODIMP ExtPack::COMGETTER(Edition)(BSTR *a_pbstrEdition)
+{
+ CheckComArgOutPointerValid(a_pbstrEdition);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ Bstr str(m->Desc.strEdition);
+ str.cloneTo(a_pbstrEdition);
+ }
+ return hrc;
+}
+
STDMETHODIMP ExtPack::COMGETTER(VRDEModule)(BSTR *a_pbstrVrdeModule)
{
CheckComArgOutPointerValid(a_pbstrVrdeModule);
diff --git a/src/VBox/Main/src-all/ExtPackUtil.cpp b/src/VBox/Main/src-all/ExtPackUtil.cpp
index cda2268f3..c7a1dacb3 100644
--- a/src/VBox/Main/src-all/ExtPackUtil.cpp
+++ b/src/VBox/Main/src-all/ExtPackUtil.cpp
@@ -96,7 +96,7 @@ void VBoxExtPackInitDesc(PVBOXEXTPACKDESC a_pExtPackDesc)
*
* @returns NULL on success, pointer to an error message on failure (caller
* deletes it).
- * @param a_pDoc Pointer to the the XML document.
+ * @param a_pDoc Pointer to the XML document.
* @param a_pExtPackDesc Where to store the extension pack descriptor.
*/
static RTCString *vboxExtPackLoadDescFromDoc(xml::Document *a_pDoc, PVBOXEXTPACKDESC a_pExtPackDesc)
diff --git a/src/VBox/Main/src-all/Global.cpp b/src/VBox/Main/src-all/Global.cpp
index 37a4098b6..6ae03726a 100644
--- a/src/VBox/Main/src-all/Global.cpp
+++ b/src/VBox/Main/src-all/Global.cpp
@@ -1,14 +1,12 @@
/* $Id: Global.cpp $ */
-
/** @file
- *
* VirtualBox COM global definitions
*
* NOTE: This file is part of both VBoxC.dll and VBoxSVC.exe.
*/
/*
- * Copyright (C) 2008-2010 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -26,295 +24,305 @@
#include <VBox/err.h>
/* static */
-const Global::OSType Global::sOSTypes[SchemaDefs::OSTypeId_COUNT] =
+const Global::OSType Global::sOSTypes[] =
{
/* NOTE1: we assume that unknown is always the first entry!
* NOTE2: please use powers of 2 when specifying the size of harddisks since
* '2GB' looks better than '1.95GB' (= 2000MB) */
- { "Other", "Other", SchemaDefs_OSTypeId_Other, "Other/Unknown",
+ { "Other", "Other", "Other", "Other/Unknown",
VBOXOSTYPE_Unknown, VBOXOSHINT_NONE,
64, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows31, "Windows 3.1",
- VBOXOSTYPE_Win31, VBOXOSHINT_NONE,
+ { "Windows", "Microsoft Windows", "Windows31", "Windows 3.1",
+ VBOXOSTYPE_Win31, VBOXOSHINT_FLOPPY,
32, 4, 1 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows95, "Windows 95",
- VBOXOSTYPE_Win95, VBOXOSHINT_NONE,
+ { "Windows", "Microsoft Windows", "Windows95", "Windows 95",
+ VBOXOSTYPE_Win95, VBOXOSHINT_FLOPPY,
64, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
- StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows98, "Windows 98",
- VBOXOSTYPE_Win98, VBOXOSHINT_NONE,
+ StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
+ { "Windows", "Microsoft Windows", "Windows98", "Windows 98",
+ VBOXOSTYPE_Win98, VBOXOSHINT_FLOPPY,
64, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
+ { "Windows", "Microsoft Windows", "WindowsMe", "Windows ME",
+ VBOXOSTYPE_WinMe, VBOXOSHINT_FLOPPY | VBOXOSHINT_USBTABLET,
+ 128, 4, 4 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_WindowsMe, "Windows Me",
- VBOXOSTYPE_WinMe, VBOXOSHINT_NONE,
- 64, 4, 4 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
- StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_WindowsNT4, "Windows NT 4",
+ { "Windows", "Microsoft Windows", "WindowsNT4", "Windows NT 4",
VBOXOSTYPE_WinNT4, VBOXOSHINT_NONE,
128, 16, 2 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
- StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows2000, "Windows 2000",
+ StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
+ { "Windows", "Microsoft Windows", "Windows2000", "Windows 2000",
VBOXOSTYPE_Win2k, VBOXOSHINT_USBTABLET,
168, 16, 4 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_WindowsXP, "Windows XP",
+ { "Windows", "Microsoft Windows", "WindowsXP", "Windows XP",
VBOXOSTYPE_WinXP, VBOXOSHINT_USBTABLET,
192, 16, 10 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_WindowsXP_64, "Windows XP (64 bit)",
+ { "Windows", "Microsoft Windows", "WindowsXP_64", "Windows XP (64 bit)",
VBOXOSTYPE_WinXP_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
192, 16, 10 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows2003, "Windows 2003",
+ { "Windows", "Microsoft Windows", "Windows2003", "Windows 2003",
VBOXOSTYPE_Win2k3, VBOXOSHINT_USBTABLET,
256, 16, 20 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows2003_64, "Windows 2003 (64 bit)",
+ { "Windows", "Microsoft Windows", "Windows2003_64", "Windows 2003 (64 bit)",
VBOXOSTYPE_Win2k3_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
256, 16, 20 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_WindowsVista, "Windows Vista",
+ { "Windows", "Microsoft Windows", "WindowsVista", "Windows Vista",
VBOXOSTYPE_WinVista, VBOXOSHINT_USBTABLET,
512, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_WindowsVista_64, "Windows Vista (64 bit)",
+ { "Windows", "Microsoft Windows", "WindowsVista_64", "Windows Vista (64 bit)",
VBOXOSTYPE_WinVista_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
512, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows2008, "Windows 2008",
+ { "Windows", "Microsoft Windows", "Windows2008", "Windows 2008",
VBOXOSTYPE_Win2k8, VBOXOSHINT_USBTABLET,
512, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows2008_64, "Windows 2008 (64 bit)",
+ { "Windows", "Microsoft Windows", "Windows2008_64", "Windows 2008 (64 bit)",
VBOXOSTYPE_Win2k8_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
512, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows7, "Windows 7",
+ { "Windows", "Microsoft Windows", "Windows7", "Windows 7",
VBOXOSTYPE_Win7, VBOXOSHINT_USBTABLET,
512, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows7_64, "Windows 7 (64 bit)",
+ { "Windows", "Microsoft Windows", "Windows7_64", "Windows 7 (64 bit)",
VBOXOSTYPE_Win7_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
512, 16, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows8, "Windows 8",
- VBOXOSTYPE_Win8, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET | VBOXOSHINT_PAE,
+ { "Windows", "Microsoft Windows", "Windows8", "Windows 8",
+ VBOXOSTYPE_Win8, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET | VBOXOSHINT_PAE,
1024,128, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_Windows8_64, "Windows 8 (64 bit)",
+ { "Windows", "Microsoft Windows", "Windows8_64", "Windows 8 (64 bit)",
VBOXOSTYPE_Win8_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
- 1536,128, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ 2048,128, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
- { "Windows", "Microsoft Windows", SchemaDefs_OSTypeId_WindowsNT, "Other Windows",
+ { "Windows", "Microsoft Windows", "Windows2012_64", "Windows 2012 (64 bit)",
+ VBOXOSTYPE_Win2k12_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
+ 2048,128, 25 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_HDA },
+ { "Windows", "Microsoft Windows", "WindowsNT", "Other Windows",
VBOXOSTYPE_WinNT, VBOXOSHINT_NONE,
512, 16, 20 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Linux22, "Linux 2.2",
+ { "Linux", "Linux", "Linux22", "Linux 2.2",
VBOXOSTYPE_Linux22, VBOXOSHINT_RTCUTC,
64, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Linux24, "Linux 2.4",
+ { "Linux", "Linux", "Linux24", "Linux 2.4",
VBOXOSTYPE_Linux24, VBOXOSHINT_RTCUTC,
128, 4, 4 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Linux24_64, "Linux 2.4 (64 bit)",
+ { "Linux", "Linux", "Linux24_64", "Linux 2.4 (64 bit)",
VBOXOSTYPE_Linux24_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
128, 4, 4 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Linux26, "Linux 2.6",
+ { "Linux", "Linux", "Linux26", "Linux 2.6",
VBOXOSTYPE_Linux26, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
256, 4, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Linux26_64, "Linux 2.6 (64 bit)",
+ { "Linux", "Linux", "Linux26_64", "Linux 2.6 (64 bit)",
VBOXOSTYPE_Linux26_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
256, 4, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_ArchLinux, "Arch Linux",
+ { "Linux", "Linux", "ArchLinux", "Arch Linux",
VBOXOSTYPE_ArchLinux, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
256, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_ArchLinux_64, "Arch Linux (64 bit)",
+ { "Linux", "Linux", "ArchLinux_64", "Arch Linux (64 bit)",
VBOXOSTYPE_ArchLinux_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
256, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Debian, "Debian",
+ { "Linux", "Linux", "Debian", "Debian",
VBOXOSTYPE_Debian, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
384, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Debian_64, "Debian (64 bit)",
+ { "Linux", "Linux", "Debian_64", "Debian (64 bit)",
VBOXOSTYPE_Debian_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
384, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97},
- { "Linux", "Linux", SchemaDefs_OSTypeId_OpenSUSE, "openSUSE",
+ { "Linux", "Linux", "OpenSUSE", "openSUSE",
VBOXOSTYPE_OpenSUSE, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_OpenSUSE_64, "openSUSE (64 bit)",
+ { "Linux", "Linux", "OpenSUSE_64", "openSUSE (64 bit)",
VBOXOSTYPE_OpenSUSE_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Fedora, "Fedora",
+ { "Linux", "Linux", "Fedora", "Fedora",
VBOXOSTYPE_FedoraCore, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
768, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Fedora_64, "Fedora (64 bit)",
+ { "Linux", "Linux", "Fedora_64", "Fedora (64 bit)",
VBOXOSTYPE_FedoraCore_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
768, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Gentoo, "Gentoo",
+ { "Linux", "Linux", "Gentoo", "Gentoo",
VBOXOSTYPE_Gentoo, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
256, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Gentoo_64, "Gentoo (64 bit)",
+ { "Linux", "Linux", "Gentoo_64", "Gentoo (64 bit)",
VBOXOSTYPE_Gentoo_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
256, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Mandriva, "Mandriva",
+ { "Linux", "Linux", "Mandriva", "Mandriva",
VBOXOSTYPE_Mandriva, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Mandriva_64, "Mandriva (64 bit)",
+ { "Linux", "Linux", "Mandriva_64", "Mandriva (64 bit)",
VBOXOSTYPE_Mandriva_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_RedHat, "Red Hat",
+ { "Linux", "Linux", "RedHat", "Red Hat",
VBOXOSTYPE_RedHat, VBOXOSHINT_RTCUTC | VBOXOSHINT_PAE,
512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_RedHat_64, "Red Hat (64 bit)",
+ { "Linux", "Linux", "RedHat_64", "Red Hat (64 bit)",
VBOXOSTYPE_RedHat_x64, VBOXOSHINT_64BIT | VBOXOSHINT_PAE | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Turbolinux, "Turbolinux",
+ { "Linux", "Linux", "Turbolinux", "Turbolinux",
VBOXOSTYPE_Turbolinux, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
384, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Turbolinux, "Turbolinux (64 bit)",
+ { "Linux", "Linux", "Turbolinux_64", "Turbolinux (64 bit)",
VBOXOSTYPE_Turbolinux_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
384, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Ubuntu, "Ubuntu",
+ { "Linux", "Linux", "Ubuntu", "Ubuntu",
VBOXOSTYPE_Ubuntu, VBOXOSHINT_RTCUTC | VBOXOSHINT_PAE | VBOXOSHINT_USBTABLET,
512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Ubuntu_64, "Ubuntu (64 bit)",
+ { "Linux", "Linux", "Ubuntu_64", "Ubuntu (64 bit)",
VBOXOSTYPE_Ubuntu_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Xandros, "Xandros",
+ { "Linux", "Linux", "Xandros", "Xandros",
VBOXOSTYPE_Xandros, VBOXOSHINT_RTCUTC,
256, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Xandros_64, "Xandros (64 bit)",
+ { "Linux", "Linux", "Xandros_64", "Xandros (64 bit)",
VBOXOSTYPE_Xandros_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
256, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Oracle, "Oracle",
+ { "Linux", "Linux", "Oracle", "Oracle",
VBOXOSTYPE_Oracle, VBOXOSHINT_RTCUTC | VBOXOSHINT_PAE,
- 512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ 512, 12, 12 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Oracle_64, "Oracle (64 bit)",
+ { "Linux", "Linux", "Oracle_64", "Oracle (64 bit)",
VBOXOSTYPE_Oracle_x64, VBOXOSHINT_64BIT | VBOXOSHINT_PAE | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_RTCUTC,
- 512, 12, 8 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
+ 512, 12, 12 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Linux", "Linux", SchemaDefs_OSTypeId_Linux, "Other Linux",
+ { "Linux", "Linux", "Linux", "Other Linux",
VBOXOSTYPE_Linux, VBOXOSHINT_RTCUTC | VBOXOSHINT_USBTABLET,
256, 12, 8 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Solaris", "Solaris", SchemaDefs_OSTypeId_Solaris, "Oracle Solaris 10 5/09 and earlier",
+ { "Solaris", "Solaris", "Solaris", "Oracle Solaris 10 5/09 and earlier",
VBOXOSTYPE_Solaris, VBOXOSHINT_NONE,
768, 12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Solaris", "Solaris", SchemaDefs_OSTypeId_Solaris_64, "Oracle Solaris 10 5/09 and earlier (64 bit)",
+ { "Solaris", "Solaris", "Solaris_64", "Oracle Solaris 10 5/09 and earlier (64 bit)",
VBOXOSTYPE_Solaris_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC,
1536, 12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Solaris", "Solaris", SchemaDefs_OSTypeId_OpenSolaris, "Oracle Solaris 10 10/09 and later",
+ { "Solaris", "Solaris", "OpenSolaris", "Oracle Solaris 10 10/09 and later",
VBOXOSTYPE_OpenSolaris, VBOXOSHINT_USBTABLET,
768, 12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Solaris", "Solaris", SchemaDefs_OSTypeId_OpenSolaris_64, "Oracle Solaris 10 10/09 and later (64 bit)",
+ { "Solaris", "Solaris", "OpenSolaris_64", "Oracle Solaris 10 10/09 and later (64 bit)",
VBOXOSTYPE_OpenSolaris_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
1536, 12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "BSD", "BSD", SchemaDefs_OSTypeId_FreeBSD, "FreeBSD",
+ { "Solaris", "Solaris", "Solaris11_64", "Oracle Solaris 11 (64 bit)",
+ VBOXOSTYPE_Solaris11_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_USBTABLET,
+ 1536, 12, 16 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_IntelAhci, StorageBus_SATA,
+ StorageControllerType_IntelAhci, StorageBus_SATA, ChipsetType_PIIX3, AudioControllerType_AC97 },
+ { "BSD", "BSD", "FreeBSD", "FreeBSD",
VBOXOSTYPE_FreeBSD, VBOXOSHINT_NONE,
128, 4, 2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "BSD", "BSD", SchemaDefs_OSTypeId_FreeBSD_64, "FreeBSD (64 bit)",
+ { "BSD", "BSD", "FreeBSD_64", "FreeBSD (64 bit)",
VBOXOSTYPE_FreeBSD_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC,
128, 4, 2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "BSD", "BSD", SchemaDefs_OSTypeId_OpenBSD, "OpenBSD",
+ { "BSD", "BSD", "OpenBSD", "OpenBSD",
VBOXOSTYPE_OpenBSD, VBOXOSHINT_HWVIRTEX,
64, 4, 2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "BSD", "BSD", SchemaDefs_OSTypeId_OpenBSD_64, "OpenBSD (64 bit)",
+ { "BSD", "BSD", "OpenBSD_64", "OpenBSD (64 bit)",
VBOXOSTYPE_OpenBSD_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC,
64, 4, 2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "BSD", "BSD", SchemaDefs_OSTypeId_NetBSD, "NetBSD",
+ { "BSD", "BSD", "NetBSD", "NetBSD",
VBOXOSTYPE_NetBSD, VBOXOSHINT_NONE,
64, 4, 2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "BSD", "BSD", SchemaDefs_OSTypeId_NetBSD_64, "NetBSD (64 bit)",
+ { "BSD", "BSD", "NetBSD_64", "NetBSD (64 bit)",
VBOXOSTYPE_NetBSD_x64, VBOXOSHINT_64BIT | VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC,
64, 4, 2 * _1G64, NetworkAdapterType_I82540EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "OS2", "IBM OS/2", SchemaDefs_OSTypeId_OS2Warp3, "OS/2 Warp 3",
- VBOXOSTYPE_OS2Warp3, VBOXOSHINT_HWVIRTEX,
+ { "OS2", "IBM OS/2", "OS2Warp3", "OS/2 Warp 3",
+ VBOXOSTYPE_OS2Warp3, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_FLOPPY,
48, 4, 1 * _1G64, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
- StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "OS2", "IBM OS/2", SchemaDefs_OSTypeId_OS2Warp4, "OS/2 Warp 4",
- VBOXOSTYPE_OS2Warp4, VBOXOSHINT_HWVIRTEX,
+ StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
+ { "OS2", "IBM OS/2", "OS2Warp4", "OS/2 Warp 4",
+ VBOXOSTYPE_OS2Warp4, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_FLOPPY,
64, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
- StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "OS2", "IBM OS/2", SchemaDefs_OSTypeId_OS2Warp45, "OS/2 Warp 4.5",
- VBOXOSTYPE_OS2Warp45, VBOXOSHINT_HWVIRTEX,
- 96, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
- StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "OS2", "IBM OS/2", SchemaDefs_OSTypeId_OS2eCS, "eComStation",
+ StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
+ { "OS2", "IBM OS/2", "OS2Warp45", "OS/2 Warp 4.5",
+ VBOXOSTYPE_OS2Warp45, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_FLOPPY,
+ 128, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
+ StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
+ { "OS2", "IBM OS/2", "OS2eCS", "eComStation",
VBOXOSTYPE_ECS, VBOXOSHINT_HWVIRTEX,
- 96, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
+ 256, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "OS2", "IBM OS/2", SchemaDefs_OSTypeId_OS2, "Other OS/2",
- VBOXOSTYPE_OS2, VBOXOSHINT_HWVIRTEX,
+ { "OS2", "IBM OS/2", "OS2", "Other OS/2",
+ VBOXOSTYPE_OS2, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_FLOPPY | VBOXOSHINT_NOUSB,
96, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 1, StorageControllerType_PIIX4, StorageBus_IDE,
- StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "MacOS", "Mac OS X", SchemaDefs_OSTypeId_MacOS, "Mac OS X Server",
+ StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
+ { "MacOS", "Mac OS X", "MacOS", "Mac OS X",
VBOXOSTYPE_MacOS, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_EFI | VBOXOSHINT_PAE | VBOXOSHINT_USBHID | VBOXOSHINT_HPET | VBOXOSHINT_USBTABLET,
- 1024, 4, 20 * _1G64, NetworkAdapterType_I82543GC, 0,
+ 2048, 4, 20 * _1G64, NetworkAdapterType_I82543GC, 0,
StorageControllerType_ICH6, StorageBus_IDE, StorageControllerType_IntelAhci, StorageBus_SATA,
ChipsetType_ICH9, AudioControllerType_HDA },
- { "MacOS", "Mac OS X", SchemaDefs_OSTypeId_MacOS_64, "Mac OS X Server (64 bit)",
+ { "MacOS", "Mac OS X", "MacOS_64", "Mac OS X (64 bit)",
VBOXOSTYPE_MacOS_x64, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_EFI | VBOXOSHINT_PAE | VBOXOSHINT_64BIT | VBOXOSHINT_USBHID | VBOXOSHINT_HPET | VBOXOSHINT_USBTABLET,
- 1024, 4, 20 * _1G64, NetworkAdapterType_I82543GC, 0,
+ 2048, 4, 20 * _1G64, NetworkAdapterType_I82543GC, 0,
StorageControllerType_ICH6, StorageBus_IDE, StorageControllerType_IntelAhci, StorageBus_SATA,
ChipsetType_ICH9, AudioControllerType_HDA },
- { "Other", "Other", SchemaDefs_OSTypeId_DOS, "DOS",
- VBOXOSTYPE_DOS, VBOXOSHINT_NONE,
+ { "Other", "Other", "DOS", "DOS",
+ VBOXOSTYPE_DOS, VBOXOSHINT_FLOPPY | VBOXOSHINT_NOUSB,
32, 4, 500 * _1M, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_SB16 },
- { "Other", "Other", SchemaDefs_OSTypeId_Netware, "Netware",
+ { "Other", "Other", "Netware", "Netware",
VBOXOSTYPE_Netware, VBOXOSHINT_HWVIRTEX,
512, 4, 4 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Other", "Other", SchemaDefs_OSTypeId_L4, "L4",
+ { "Other", "Other", "L4", "L4",
VBOXOSTYPE_L4, VBOXOSHINT_NONE,
64, 4, 2 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Other", "Other", SchemaDefs_OSTypeId_QNX, "QNX",
+ { "Other", "Other", "QNX", "QNX",
VBOXOSTYPE_QNX, VBOXOSHINT_HWVIRTEX,
512, 4, 4 * _1G64, NetworkAdapterType_Am79C973, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_PIIX4, StorageBus_IDE, ChipsetType_PIIX3, AudioControllerType_AC97 },
- { "Other", "Other", SchemaDefs_OSTypeId_JRockitVE, "JRockitVE",
+ { "Other", "Other", "JRockitVE", "JRockitVE",
VBOXOSTYPE_JRockitVE, VBOXOSHINT_HWVIRTEX | VBOXOSHINT_IOAPIC | VBOXOSHINT_PAE,
1024, 4, 8 * _1G64, NetworkAdapterType_I82545EM, 0, StorageControllerType_PIIX4, StorageBus_IDE,
StorageControllerType_BusLogic, StorageBus_SCSI, ChipsetType_PIIX3, AudioControllerType_AC97 },
};
+uint32_t Global::cOSTypes = RT_ELEMENTS(Global::sOSTypes);
+
/**
* Returns an OS Type ID for the given VBOXOSTYPE value.
*
@@ -331,10 +339,22 @@ const char *Global::OSTypeId(VBOXOSTYPE aOSType)
return sOSTypes[i].id;
}
- AssertMsgFailed(("No record for VBOXOSTYPE %d\n", aOSType));
return sOSTypes[0].id;
}
+/*static*/ uint32_t Global::getMaxNetworkAdapters(ChipsetType_T aChipsetType)
+{
+ switch (aChipsetType)
+ {
+ case ChipsetType_PIIX3:
+ return 8;
+ case ChipsetType_ICH9:
+ return 36;
+ default:
+ return 0;
+ }
+}
+
/*static*/ const char *
Global::stringifyMachineState(MachineState_T aState)
{
@@ -519,5 +539,4 @@ Global::vboxStatusCodeToCOM(int aVBoxStatus)
}
}
-
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/src-all/HashedPw.cpp b/src/VBox/Main/src-all/HashedPw.cpp
new file mode 100644
index 000000000..4f2385ee4
--- /dev/null
+++ b/src/VBox/Main/src-all/HashedPw.cpp
@@ -0,0 +1,103 @@
+/* $Id: HashedPw.cpp $ */
+/** @file
+ * Main - Password Hashing
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "HashedPw.h"
+
+#include <iprt/assert.h>
+#include <iprt/ctype.h>
+#include <iprt/sha.h>
+#include <iprt/string.h>
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+/**
+ * The prefix of a hashed password.
+ */
+static const char s_szHashedPwPrefix[] = "#SHA-512#";
+
+
+/**
+ * Checks if the password is a hashed one or not.
+ *
+ * Empty password are not considered hashed.
+ *
+ * @returns true if hashed, false if not.
+ * @param a_pstrPassword Password to inspect.
+ */
+bool VBoxIsPasswordHashed(RTCString const *a_pstrPassword)
+{
+ /* prefix */
+ if (!a_pstrPassword->startsWith(s_szHashedPwPrefix))
+ return false;
+
+ /* salt (optional) */
+ const char *pszSalt = a_pstrPassword->c_str() + sizeof(s_szHashedPwPrefix) - 1;
+ const char *pszSaltEnd = strchr(pszSalt, '#');
+ if (!pszSaltEnd)
+ return false;
+ while (pszSalt != pszSaltEnd)
+ {
+ if (!RT_C_IS_XDIGIT(*pszSalt))
+ return false;
+ pszSalt++;
+ }
+
+ /* hash */
+ uint8_t abHash[RTSHA512_HASH_SIZE];
+ int rc = RTSha512FromString(pszSaltEnd + 1, abHash);
+ return RT_SUCCESS(rc);
+}
+
+
+/**
+ * Hashes a plain text password.
+ *
+ * @param a_pstrPassword Plain text password to hash. This is both
+ * input and output.
+ */
+void VBoxHashPassword(RTCString *a_pstrPassword)
+{
+ AssertReturnVoid(!VBoxIsPasswordHashed(a_pstrPassword));
+
+ char szHashedPw[sizeof(s_szHashedPwPrefix) + 1 + RTSHA512_DIGEST_LEN];
+ if (a_pstrPassword->isEmpty())
+ szHashedPw[0] = '\0';
+ else
+ {
+ /* prefix */
+ char *pszHashedPw = szHashedPw;
+ strcpy(pszHashedPw, s_szHashedPwPrefix);
+ pszHashedPw += sizeof(s_szHashedPwPrefix) - 1;
+
+ /* salt */
+ *pszHashedPw++ = '#'; /* no salt yet */
+
+ /* hash */
+ uint8_t abHash[RTSHA512_HASH_SIZE];
+ RTSha512(a_pstrPassword->c_str(), a_pstrPassword->length(), abHash);
+ int rc = RTSha512ToString(abHash, pszHashedPw, sizeof(szHashedPw) - (pszHashedPw - &szHashedPw[0]));
+ AssertReleaseRC(rc);
+ }
+
+ *a_pstrPassword = szHashedPw;
+}
+
diff --git a/src/VBox/Main/src-all/PciDeviceAttachmentImpl.cpp b/src/VBox/Main/src-all/PCIDeviceAttachmentImpl.cpp
index 2d5e66ed6..e984238fa 100644
--- a/src/VBox/Main/src-all/PciDeviceAttachmentImpl.cpp
+++ b/src/VBox/Main/src-all/PCIDeviceAttachmentImpl.cpp
@@ -1,4 +1,4 @@
-/* $Id: PciDeviceAttachmentImpl.cpp $ */
+/* $Id: PCIDeviceAttachmentImpl.cpp $ */
/** @file
*
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -17,12 +17,12 @@
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
-#include "PciDeviceAttachmentImpl.h"
+#include "PCIDeviceAttachmentImpl.h"
#include "AutoCaller.h"
#include "Global.h"
#include "Logging.h"
-struct PciDeviceAttachment::Data
+struct PCIDeviceAttachment::Data
{
Data(const Bstr &aDevName,
LONG aHostAddress,
@@ -43,13 +43,13 @@ struct PciDeviceAttachment::Data
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
-HRESULT PciDeviceAttachment::FinalConstruct()
+HRESULT PCIDeviceAttachment::FinalConstruct()
{
LogFlowThisFunc(("\n"));
return BaseFinalConstruct();
}
-void PciDeviceAttachment::FinalRelease()
+void PCIDeviceAttachment::FinalRelease()
{
LogFlowThisFunc(("\n"));
uninit();
@@ -58,7 +58,7 @@ void PciDeviceAttachment::FinalRelease()
// public initializer/uninitializer for internal purposes only
/////////////////////////////////////////////////////////////////////////////
-HRESULT PciDeviceAttachment::init(IMachine *aParent,
+HRESULT PCIDeviceAttachment::init(IMachine *aParent,
const Bstr &aDevName,
LONG aHostAddress,
LONG aGuestAddress,
@@ -70,15 +70,15 @@ HRESULT PciDeviceAttachment::init(IMachine *aParent,
return m != NULL ? S_OK : E_FAIL;
}
-HRESULT PciDeviceAttachment::loadSettings(IMachine *aParent,
- const settings::HostPciDeviceAttachment &hpda)
+HRESULT PCIDeviceAttachment::loadSettings(IMachine *aParent,
+ const settings::HostPCIDeviceAttachment &hpda)
{
Bstr bname(hpda.strDeviceName);
return init(aParent, bname, hpda.uHostAddress, hpda.uGuestAddress, TRUE);
}
-HRESULT PciDeviceAttachment::saveSettings(settings::HostPciDeviceAttachment &data)
+HRESULT PCIDeviceAttachment::saveSettings(settings::HostPCIDeviceAttachment &data)
{
Assert(m);
data.uHostAddress = m->HostAddress;
@@ -92,7 +92,7 @@ HRESULT PciDeviceAttachment::saveSettings(settings::HostPciDeviceAttachment &dat
* Uninitializes the instance.
* Called from FinalRelease().
*/
-void PciDeviceAttachment::uninit()
+void PCIDeviceAttachment::uninit()
{
if (m)
{
@@ -101,36 +101,36 @@ void PciDeviceAttachment::uninit()
}
}
-// IPciDeviceAttachment properties
+// IPCIDeviceAttachment properties
/////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP PciDeviceAttachment::COMGETTER(Name)(BSTR * aName)
+STDMETHODIMP PCIDeviceAttachment::COMGETTER(Name)(BSTR * aName)
{
CheckComArgOutPointerValid(aName);
m->DevName.cloneTo(aName);
return S_OK;
}
-STDMETHODIMP PciDeviceAttachment::COMGETTER(IsPhysicalDevice)(BOOL * aPhysical)
+STDMETHODIMP PCIDeviceAttachment::COMGETTER(IsPhysicalDevice)(BOOL * aPhysical)
{
CheckComArgOutPointerValid(aPhysical);
*aPhysical = m->fPhysical;
return S_OK;
}
-STDMETHODIMP PciDeviceAttachment::COMGETTER(HostAddress)(LONG * aHostAddress)
+STDMETHODIMP PCIDeviceAttachment::COMGETTER(HostAddress)(LONG * aHostAddress)
{
*aHostAddress = m->HostAddress;
return S_OK;
}
-STDMETHODIMP PciDeviceAttachment::COMGETTER(GuestAddress)(LONG * aGuestAddress)
+STDMETHODIMP PCIDeviceAttachment::COMGETTER(GuestAddress)(LONG * aGuestAddress)
{
*aGuestAddress = m->GuestAddress;
return S_OK;
}
#ifdef VBOX_WITH_XPCOM
-NS_DECL_CLASSINFO(PciDeviceAttachment)
-NS_IMPL_THREADSAFE_ISUPPORTS1_CI(PciDeviceAttachment, IPciDeviceAttachment)
+NS_DECL_CLASSINFO(PCIDeviceAttachment)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(PCIDeviceAttachment, IPCIDeviceAttachment)
#endif
diff --git a/src/VBox/Main/src-all/ProgressImpl.cpp b/src/VBox/Main/src-all/ProgressImpl.cpp
index 6fa4eab43..3d78b2bc2 100644
--- a/src/VBox/Main/src-all/ProgressImpl.cpp
+++ b/src/VBox/Main/src-all/ProgressImpl.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -819,10 +819,10 @@ STDMETHODIMP Progress::WaitForCompletion(LONG aTimeout)
while (!mCompleted && (fForever || timeLeft > 0))
{
mWaitersCount++;
- alock.leave();
+ alock.release();
vrc = RTSemEventMultiWait(mCompletedSem,
fForever ? RT_INDEFINITE_WAIT : (RTMSINTERVAL)timeLeft);
- alock.enter();
+ alock.acquire();
mWaitersCount--;
/* the last waiter resets the semaphore */
@@ -883,10 +883,10 @@ STDMETHODIMP Progress::WaitForOperationCompletion(ULONG aOperation, LONG aTimeou
&& (fForever || timeLeft > 0))
{
mWaitersCount ++;
- alock.leave();
+ alock.release();
vrc = RTSemEventMultiWait(mCompletedSem,
fForever ? RT_INDEFINITE_WAIT : (unsigned) timeLeft);
- alock.enter();
+ alock.acquire();
mWaitersCount--;
/* the last waiter resets the semaphore */
@@ -1234,7 +1234,7 @@ HRESULT Progress::notifyComplete(HRESULT aResultCode,
/**
* Marks the operation as complete and attaches full error info.
*
- * See com::SupportErrorInfoImpl::setError(HRESULT, const GUID &, const wchar_t
+ * See VirtualBoxBase::setError(HRESULT, const GUID &, const wchar_t
* *, const char *, ...) for more info.
*
* @param aResultCode Operation result (error) code, must not be S_OK.
@@ -1663,9 +1663,9 @@ STDMETHODIMP CombinedProgress::WaitForCompletion(LONG aTimeout)
while (!mCompleted && (forever || timeLeft > 0))
{
- alock.leave();
+ alock.release();
rc = mProgresses.back()->WaitForCompletion(forever ? -1 : (LONG) timeLeft);
- alock.enter();
+ alock.acquire();
if (SUCCEEDED(rc))
rc = checkProgress();
@@ -1747,11 +1747,11 @@ STDMETHODIMP CombinedProgress::WaitForOperationCompletion(ULONG aOperation, LONG
while (!mCompleted && aOperation >= m_ulCurrentOperation &&
(forever || timeLeft > 0))
{
- alock.leave();
+ alock.release();
/* wait for the appropriate progress operation completion */
rc = mProgresses[progress]-> WaitForOperationCompletion(operation,
forever ? -1 : (LONG) timeLeft);
- alock.enter();
+ alock.acquire();
if (SUCCEEDED(rc))
rc = checkProgress();
diff --git a/src/VBox/Main/src-all/VirtualBoxBase.cpp b/src/VBox/Main/src-all/VirtualBoxBase.cpp
index 9f819e46e..08331bcbb 100644
--- a/src/VBox/Main/src-all/VirtualBoxBase.cpp
+++ b/src/VBox/Main/src-all/VirtualBoxBase.cpp
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -19,6 +19,9 @@
#include <iprt/semaphore.h>
#include <iprt/asm.h>
+#include <iprt/cpp/exception.h>
+
+#include <typeinfo>
#if !defined (VBOX_WITH_XPCOM)
#include <windows.h>
@@ -208,9 +211,9 @@ HRESULT VirtualBoxBase::addCaller(State *aState /* = NULL */,
LogFlowThisFunc(("Waiting for AutoInitSpan/AutoReinitSpan to finish...\n"));
- stateLock.leave();
+ stateLock.release();
RTSemEventMultiWait (mInitUninitSem, RT_INDEFINITE_WAIT);
- stateLock.enter();
+ stateLock.acquire();
if (-- mInitUninitWaiters == 0)
{
@@ -294,6 +297,69 @@ void VirtualBoxBase::releaseCaller()
}
/**
+ * Handles unexpected exceptions by turning them into COM errors in release
+ * builds or by hitting a breakpoint in the release builds.
+ *
+ * Usage pattern:
+ * @code
+ try
+ {
+ // ...
+ }
+ catch (LaLalA)
+ {
+ // ...
+ }
+ catch (...)
+ {
+ rc = VirtualBox::handleUnexpectedExceptions(this, RT_SRC_POS);
+ }
+ * @endcode
+ *
+ * @param aThis object where the exception happened
+ * @param RT_SRC_POS_DECL "RT_SRC_POS" macro instantiation.
+ * */
+/* static */
+HRESULT VirtualBoxBase::handleUnexpectedExceptions(VirtualBoxBase *const aThis, RT_SRC_POS_DECL)
+{
+ try
+ {
+ /* re-throw the current exception */
+ throw;
+ }
+ catch (const RTCError &err) // includes all XML exceptions
+ {
+ return setErrorInternal(E_FAIL, aThis->getClassIID(), aThis->getComponentName(),
+ Utf8StrFmt(tr("%s.\n%s[%d] (%s)"),
+ err.what(),
+ pszFile, iLine, pszFunction).c_str(),
+ false /* aWarning */,
+ true /* aLogIt */);
+ }
+ catch (const std::exception &err)
+ {
+ return setErrorInternal(E_FAIL, aThis->getClassIID(), aThis->getComponentName(),
+ Utf8StrFmt(tr("Unexpected exception: %s [%s]\n%s[%d] (%s)"),
+ err.what(), typeid(err).name(),
+ pszFile, iLine, pszFunction).c_str(),
+ false /* aWarning */,
+ true /* aLogIt */);
+ }
+ catch (...)
+ {
+ return setErrorInternal(E_FAIL, aThis->getClassIID(), aThis->getComponentName(),
+ Utf8StrFmt(tr("Unknown exception\n%s[%d] (%s)"),
+ pszFile, iLine, pszFunction).c_str(),
+ false /* aWarning */,
+ true /* aLogIt */);
+ }
+
+ /* should not get here */
+ AssertFailed();
+ return E_FAIL;
+}
+
+/**
* Sets error info for the current thread. This is an internal function that
* gets eventually called by all public variants. If @a aWarning is
* @c true, then the highest (31) bit in the @a aResultCode value which
@@ -305,7 +371,7 @@ void VirtualBoxBase::releaseCaller()
HRESULT VirtualBoxBase::setErrorInternal(HRESULT aResultCode,
const GUID &aIID,
const char *pcszComponent,
- const Utf8Str &aText,
+ Utf8Str aText,
bool aWarning,
bool aLogIt)
{
@@ -327,7 +393,6 @@ HRESULT VirtualBoxBase::setErrorInternal(HRESULT aResultCode,
AssertReturn((!aWarning && FAILED(aResultCode)) ||
(aWarning && aResultCode != S_OK),
E_FAIL);
- AssertReturn(!aText.isEmpty(), E_FAIL);
/* reset the error severity bit if it's a warning */
if (aWarning)
@@ -335,6 +400,36 @@ HRESULT VirtualBoxBase::setErrorInternal(HRESULT aResultCode,
HRESULT rc = S_OK;
+ if (aText.isEmpty())
+ {
+ /* Some default info */
+ switch (aResultCode)
+ {
+ case E_INVALIDARG: aText = "A parameter has an invalid value"; break;
+ case E_POINTER: aText = "A parameter is an invalid pointer"; break;
+ case E_UNEXPECTED: aText = "The result of the operation is unexpected"; break;
+ case E_ACCESSDENIED: aText = "The access to an object is not allowed"; break;
+ case E_OUTOFMEMORY: aText = "The allocation of new memory failed"; break;
+ case E_NOTIMPL: aText = "The requested operation is not implemented"; break;
+ case E_NOINTERFACE: aText = "The requested interface is not implemented"; break;
+ case E_FAIL: aText = "A general error occurred"; break;
+ case E_ABORT: aText = "The operation was canceled"; break;
+ case VBOX_E_OBJECT_NOT_FOUND: aText = "Object corresponding to the supplied arguments does not exist"; break;
+ case VBOX_E_INVALID_VM_STATE: aText = "Current virtual machine state prevents the operation"; break;
+ case VBOX_E_VM_ERROR: aText = "Virtual machine error occurred attempting the operation"; break;
+ case VBOX_E_FILE_ERROR: aText = "File not accessible or erroneous file contents"; break;
+ case VBOX_E_IPRT_ERROR: aText = "Runtime subsystem error"; break;
+ case VBOX_E_PDM_ERROR: aText = "Pluggable Device Manager error"; break;
+ case VBOX_E_INVALID_OBJECT_STATE: aText = "Current object state prohibits operation"; break;
+ case VBOX_E_HOST_ERROR: aText = "Host operating system related error"; break;
+ case VBOX_E_NOT_SUPPORTED: aText = "Requested operation is not supported"; break;
+ case VBOX_E_XML_ERROR: aText = "Invalid XML found"; break;
+ case VBOX_E_INVALID_SESSION_STATE: aText = "Current session state prohibits operation"; break;
+ case VBOX_E_OBJECT_IN_USE: aText = "Object being in use prohibits operation"; break;
+ default: aText = "Unknown error"; break;
+ }
+ }
+
do
{
ComObjPtr<VirtualBoxErrorInfo> info;
@@ -455,6 +550,24 @@ HRESULT VirtualBoxBase::setErrorInternal(HRESULT aResultCode,
* @param pcsz
* @return
*/
+HRESULT VirtualBoxBase::setError(HRESULT aResultCode)
+{
+ return setErrorInternal(aResultCode,
+ this->getClassIID(),
+ this->getComponentName(),
+ "",
+ false /* aWarning */,
+ true /* aLogIt */);
+}
+
+/**
+ * Shortcut instance method to calling the static setErrorInternal with the
+ * class interface ID and component name inserted correctly. This uses the
+ * virtual getClassIID() and getComponentName() methods which are automatically
+ * defined by the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro.
+ * @param aResultCode
+ * @return
+ */
HRESULT VirtualBoxBase::setError(HRESULT aResultCode, const char *pcsz, ...)
{
va_list args;
@@ -470,6 +583,132 @@ HRESULT VirtualBoxBase::setError(HRESULT aResultCode, const char *pcsz, ...)
}
/**
+ * Shortcut instance method to calling the static setErrorInternal with the
+ * class interface ID and component name inserted correctly. This uses the
+ * virtual getClassIID() and getComponentName() methods which are automatically
+ * defined by the VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT macro.
+ * @param ei
+ * @return
+ */
+HRESULT VirtualBoxBase::setError(const com::ErrorInfo &ei)
+{
+ /* whether multi-error mode is turned on */
+ bool preserve = MultiResult::isMultiEnabled();
+
+ HRESULT rc = S_OK;
+
+ do
+ {
+ ComObjPtr<VirtualBoxErrorInfo> info;
+ rc = info.createObject();
+ if (FAILED(rc)) break;
+
+#if !defined (VBOX_WITH_XPCOM)
+
+ ComPtr<IVirtualBoxErrorInfo> curInfo;
+ if (preserve)
+ {
+ /* get the current error info if any */
+ ComPtr<IErrorInfo> err;
+ rc = ::GetErrorInfo (0, err.asOutParam());
+ if (FAILED(rc)) break;
+ rc = err.queryInterfaceTo(curInfo.asOutParam());
+ if (FAILED(rc))
+ {
+ /* create a IVirtualBoxErrorInfo wrapper for the native
+ * IErrorInfo object */
+ ComObjPtr<VirtualBoxErrorInfo> wrapper;
+ rc = wrapper.createObject();
+ if (SUCCEEDED(rc))
+ {
+ rc = wrapper->init (err);
+ if (SUCCEEDED(rc))
+ curInfo = wrapper;
+ }
+ }
+ }
+ /* On failure, curInfo will stay null */
+ Assert(SUCCEEDED(rc) || curInfo.isNull());
+
+ /* set the current error info and preserve the previous one if any */
+ rc = info->init(ei, curInfo);
+ if (FAILED(rc)) break;
+
+ ComPtr<IErrorInfo> err;
+ rc = info.queryInterfaceTo(err.asOutParam());
+ if (SUCCEEDED(rc))
+ rc = ::SetErrorInfo (0, err);
+
+#else // !defined (VBOX_WITH_XPCOM)
+
+ nsCOMPtr <nsIExceptionService> es;
+ es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
+ if (NS_SUCCEEDED(rc))
+ {
+ nsCOMPtr <nsIExceptionManager> em;
+ rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
+ if (FAILED(rc)) break;
+
+ ComPtr<IVirtualBoxErrorInfo> curInfo;
+ if (preserve)
+ {
+ /* get the current error info if any */
+ ComPtr<nsIException> ex;
+ rc = em->GetCurrentException (ex.asOutParam());
+ if (FAILED(rc)) break;
+ rc = ex.queryInterfaceTo(curInfo.asOutParam());
+ if (FAILED(rc))
+ {
+ /* create a IVirtualBoxErrorInfo wrapper for the native
+ * nsIException object */
+ ComObjPtr<VirtualBoxErrorInfo> wrapper;
+ rc = wrapper.createObject();
+ if (SUCCEEDED(rc))
+ {
+ rc = wrapper->init (ex);
+ if (SUCCEEDED(rc))
+ curInfo = wrapper;
+ }
+ }
+ }
+ /* On failure, curInfo will stay null */
+ Assert(SUCCEEDED(rc) || curInfo.isNull());
+
+ /* set the current error info and preserve the previous one if any */
+ rc = info->init(ei, curInfo);
+ if (FAILED(rc)) break;
+
+ ComPtr<nsIException> ex;
+ rc = info.queryInterfaceTo(ex.asOutParam());
+ if (SUCCEEDED(rc))
+ rc = em->SetCurrentException (ex);
+ }
+ else if (rc == NS_ERROR_UNEXPECTED)
+ {
+ /*
+ * It is possible that setError() is being called by the object
+ * after the XPCOM shutdown sequence has been initiated
+ * (for example, when XPCOM releases all instances it internally
+ * references, which can cause object's FinalConstruct() and then
+ * uninit()). In this case, do_GetService() above will return
+ * NS_ERROR_UNEXPECTED and it doesn't actually make sense to
+ * set the exception (nobody will be able to read it).
+ */
+ LogWarningFunc(("Will not set an exception because nsIExceptionService is not available "
+ "(NS_ERROR_UNEXPECTED). XPCOM is being shutdown?\n"));
+ rc = NS_OK;
+ }
+
+#endif // !defined (VBOX_WITH_XPCOM)
+ }
+ while (0);
+
+ AssertComRC (rc);
+
+ return SUCCEEDED(rc) ? ei.getResultCode() : rc;
+}
+
+/**
* Like setError(), but sets the "warning" bit in the call to setErrorInternal().
* @param aResultCode
* @param pcsz
@@ -565,7 +804,7 @@ AutoInitSpan::AutoInitSpan(VirtualBoxBase *aObj,
}
/**
- * Places the managed VirtualBoxBase object to Ready/Limited state if the
+ * Places the managed VirtualBoxBase object to Ready/Limited state if the
* initialization succeeded or partly succeeded, or places it to InitFailed
* state and calls the object's uninit() method.
*
@@ -602,8 +841,8 @@ AutoInitSpan::~AutoInitSpan()
else
{
mObj->setState(VirtualBoxBase::InitFailed);
- /* leave the lock to prevent nesting when uninit() is called */
- stateLock.leave();
+ /* release the lock to prevent nesting when uninit() is called */
+ stateLock.release();
/* call uninit() to let the object uninit itself after failed init() */
mObj->uninit();
/* Note: the object may no longer exist here (for example, it can call
@@ -732,9 +971,9 @@ AutoUninitSpan::AutoUninitSpan(VirtualBoxBase *aObj)
LogFlowFunc(("{%p}: Waiting for AutoUninitSpan to finish...\n",
mObj));
- stateLock.leave();
+ stateLock.release();
RTSemEventMultiWait(mObj->mInitUninitSem, RT_INDEFINITE_WAIT);
- stateLock.enter();
+ stateLock.acquire();
if (--mObj->mInitUninitWaiters == 0)
{
@@ -761,7 +1000,7 @@ AutoUninitSpan::AutoUninitSpan(VirtualBoxBase *aObj)
LogFlowFunc(("{%p}: Waiting for callers (%d) to drop to zero...\n",
mObj, mObj->mCallers));
- stateLock.leave();
+ stateLock.release();
RTSemEventWait(mObj->mZeroCallersSem, RT_INDEFINITE_WAIT);
}
}
diff --git a/src/VBox/Main/src-all/VirtualBoxErrorInfoImpl.cpp b/src/VBox/Main/src-all/VirtualBoxErrorInfoImpl.cpp
index 6ad17a37f..8aea252f6 100644
--- a/src/VBox/Main/src-all/VirtualBoxErrorInfoImpl.cpp
+++ b/src/VBox/Main/src-all/VirtualBoxErrorInfoImpl.cpp
@@ -1,10 +1,10 @@
/** @file
*
- * VirtualBoxErrorInfo COM classe implementation
+ * VirtualBoxErrorInfo COM class implementation
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -18,6 +18,8 @@
#include "VirtualBoxErrorInfoImpl.h"
#include "Logging.h"
+#include <VBox/com/ErrorInfo.h>
+
// public initializer/uninitializer for internal purposes only
////////////////////////////////////////////////////////////////////////////////
@@ -36,10 +38,35 @@ HRESULT VirtualBoxErrorInfo::init(HRESULT aResultCode,
return S_OK;
}
+HRESULT VirtualBoxErrorInfo::init(const com::ErrorInfo &info,
+ IVirtualBoxErrorInfo *aNext)
+{
+ m_resultCode = info.getResultCode();
+ m_IID = info.getInterfaceID();
+ m_strComponent = info.getComponent();
+ m_strText = info.getText();
+
+ /* Recursively create VirtualBoxErrorInfo instances for the next objects. */
+ const com::ErrorInfo *pInfo = info.getNext();
+ if (pInfo)
+ {
+ ComObjPtr<VirtualBoxErrorInfo> nextEI;
+ HRESULT rc = nextEI.createObject();
+ if (FAILED(rc)) return rc;
+ rc = nextEI->init(*pInfo, aNext);
+ if (FAILED(rc)) return rc;
+ mNext = nextEI;
+ }
+ else
+ mNext = aNext;
+
+ return S_OK;
+}
+
// IVirtualBoxErrorInfo properties
////////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(ResultCode) (LONG *aResultCode)
+STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(ResultCode)(LONG *aResultCode)
{
CheckComArgOutPointerValid(aResultCode);
@@ -47,7 +74,7 @@ STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(ResultCode) (LONG *aResultCode)
return S_OK;
}
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(InterfaceID) (BSTR *aIID)
+STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(InterfaceID)(BSTR *aIID)
{
CheckComArgOutPointerValid(aIID);
@@ -55,7 +82,7 @@ STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(InterfaceID) (BSTR *aIID)
return S_OK;
}
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Component) (BSTR *aComponent)
+STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Component)(BSTR *aComponent)
{
CheckComArgOutPointerValid(aComponent);
@@ -63,7 +90,7 @@ STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Component) (BSTR *aComponent)
return S_OK;
}
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Text) (BSTR *aText)
+STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Text)(BSTR *aText)
{
CheckComArgOutPointerValid(aText);
@@ -71,7 +98,7 @@ STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Text) (BSTR *aText)
return S_OK;
}
-STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Next) (IVirtualBoxErrorInfo **aNext)
+STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Next)(IVirtualBoxErrorInfo **aNext)
{
CheckComArgOutPointerValid(aNext);
@@ -85,7 +112,7 @@ STDMETHODIMP VirtualBoxErrorInfo::COMGETTER(Next) (IVirtualBoxErrorInfo **aNext)
* Initializes itself by fetching error information from the given error info
* object.
*/
-HRESULT VirtualBoxErrorInfo::init (IErrorInfo *aInfo)
+HRESULT VirtualBoxErrorInfo::init(IErrorInfo *aInfo)
{
AssertReturn(aInfo, E_FAIL);
@@ -97,14 +124,14 @@ HRESULT VirtualBoxErrorInfo::init (IErrorInfo *aInfo)
m_resultCode = S_OK;
rc = aInfo->GetGUID(m_IID.asOutParam());
- AssertComRC (rc);
+ AssertComRC(rc);
Bstr bstrComponent;
rc = aInfo->GetSource(bstrComponent.asOutParam());
- AssertComRC (rc);
+ AssertComRC(rc);
m_strComponent = bstrComponent;
Bstr bstrText;
rc = aInfo->GetDescription(bstrText.asOutParam());
- AssertComRC (rc);
+ AssertComRC(rc);
m_strText = bstrText;
return S_OK;
@@ -113,33 +140,33 @@ HRESULT VirtualBoxErrorInfo::init (IErrorInfo *aInfo)
// IErrorInfo methods
////////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP VirtualBoxErrorInfo::GetDescription (BSTR *description)
+STDMETHODIMP VirtualBoxErrorInfo::GetDescription(BSTR *description)
{
- return COMGETTER(Text) (description);
+ return COMGETTER(Text)(description);
}
-STDMETHODIMP VirtualBoxErrorInfo::GetGUID (GUID *guid)
+STDMETHODIMP VirtualBoxErrorInfo::GetGUID(GUID *guid)
{
Bstr iid;
- HRESULT rc = COMGETTER(InterfaceID) (iid.asOutParam());
+ HRESULT rc = COMGETTER(InterfaceID)(iid.asOutParam());
if (SUCCEEDED(rc))
*guid = Guid(iid).ref();
return rc;
}
-STDMETHODIMP VirtualBoxErrorInfo::GetHelpContext (DWORD *pdwHelpContext)
+STDMETHODIMP VirtualBoxErrorInfo::GetHelpContext(DWORD *pdwHelpContext)
{
return E_NOTIMPL;
}
-STDMETHODIMP VirtualBoxErrorInfo::GetHelpFile (BSTR *pbstrHelpFile)
+STDMETHODIMP VirtualBoxErrorInfo::GetHelpFile(BSTR *pbstrHelpFile)
{
return E_NOTIMPL;
}
-STDMETHODIMP VirtualBoxErrorInfo::GetSource (BSTR *source)
+STDMETHODIMP VirtualBoxErrorInfo::GetSource(BSTR *source)
{
- return COMGETTER(Component) (source);
+ return COMGETTER(Component)(source);
}
#else // defined(VBOX_WITH_XPCOM)
@@ -179,7 +206,7 @@ HRESULT VirtualBoxErrorInfo::init(nsIException *aInfo)
////////////////////////////////////////////////////////////////////////////////
/* readonly attribute string message; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetMessage (char **aMessage)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetMessage(char **aMessage)
{
CheckComArgOutPointerValid(aMessage);
@@ -188,71 +215,71 @@ NS_IMETHODIMP VirtualBoxErrorInfo::GetMessage (char **aMessage)
}
/* readonly attribute nsresult result; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetResult (nsresult *aResult)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetResult(nsresult *aResult)
{
if (!aResult)
return NS_ERROR_INVALID_POINTER;
PRInt32 lrc;
- nsresult rc = COMGETTER(ResultCode) (&lrc);
+ nsresult rc = COMGETTER(ResultCode)(&lrc);
if (SUCCEEDED(rc))
*aResult = lrc;
return rc;
}
/* readonly attribute string name; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetName (char ** /* aName */)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetName(char ** /* aName */)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute string filename; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetFilename (char ** /* aFilename */)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetFilename(char ** /* aFilename */)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute PRUint32 lineNumber; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetLineNumber (PRUint32 * /* aLineNumber */)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetLineNumber(PRUint32 * /* aLineNumber */)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute PRUint32 columnNumber; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetColumnNumber (PRUint32 * /*aColumnNumber */)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetColumnNumber(PRUint32 * /*aColumnNumber */)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsIStackFrame location; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetLocation (nsIStackFrame ** /* aLocation */)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetLocation(nsIStackFrame ** /* aLocation */)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsIException inner; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetInner (nsIException **aInner)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetInner(nsIException **aInner)
{
ComPtr<IVirtualBoxErrorInfo> info;
- nsresult rv = COMGETTER(Next) (info.asOutParam());
+ nsresult rv = COMGETTER(Next)(info.asOutParam());
if (FAILED(rv)) return rv;
return info.queryInterfaceTo(aInner);
}
/* readonly attribute nsISupports data; */
-NS_IMETHODIMP VirtualBoxErrorInfo::GetData (nsISupports ** /* aData */)
+NS_IMETHODIMP VirtualBoxErrorInfo::GetData(nsISupports ** /* aData */)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
-/* string toString (); */
-NS_IMETHODIMP VirtualBoxErrorInfo::ToString (char ** /* retval */)
+/* string toString(); */
+NS_IMETHODIMP VirtualBoxErrorInfo::ToString(char ** /* retval */)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
-NS_IMPL_THREADSAFE_ISUPPORTS2 (VirtualBoxErrorInfo,
- nsIException, IVirtualBoxErrorInfo)
+NS_IMPL_THREADSAFE_ISUPPORTS2(VirtualBoxErrorInfo,
+ nsIException, IVirtualBoxErrorInfo)
#endif // defined(VBOX_WITH_XPCOM)
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/src-all/win/VirtualBox_rgs.xsl b/src/VBox/Main/src-all/win/VirtualBox_rgs.xsl
index aca873983..0b2e4ba93 100644
--- a/src/VBox/Main/src-all/win/VirtualBox_rgs.xsl
+++ b/src/VBox/Main/src-all/win/VirtualBox_rgs.xsl
@@ -5,15 +5,15 @@
* registry definitions necessary to properly register
* VirtualBox Main API COM components.
- Copyright (C) 2007 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2007 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet version="1.0"
diff --git a/src/VBox/Main/src-all/win/comregister.cmd b/src/VBox/Main/src-all/win/comregister.cmd
index 6a38f5ed7..1f8e312f6 100644
--- a/src/VBox/Main/src-all/win/comregister.cmd
+++ b/src/VBox/Main/src-all/win/comregister.cmd
@@ -1,25 +1,106 @@
@echo off
+REM $Id: comregister.cmd $
+REM
+REM Script to register the VirtualBox COM classes
+REM (both inproc and out-of-process)
+REM
+
+REM
+REM Copyright (C) 2006-2011 Oracle Corporation
+REM
+REM This file is part of VirtualBox Open Source Edition (OSE), as
+REM available from http://www.virtualbox.org. This file is free software;
+REM you can redistribute it and/or modify it under the terms of the GNU
+REM General Public License (GPL) as published by the Free Software
+REM Foundation, in version 2 as it comes in the "COPYING" file of the
+REM VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+REM hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+REM
+
+setlocal
+
+REM
+REM Figure out where the script lives first, so that we can invoke the
+REM correct VBoxSVC and register the right VBoxC.dll.
+REM
+
+REM Determin the current directory.
+set _SCRIPT_CURDIR=%CD%
+for /f "tokens=*" %%d in ('cd') do set _SCRIPT_CURDIR=%%d
+
+REM Determin a correct self - by %0.
+set _SCRIPT_SELF=%0
+if exist "%_SCRIPT_SELF%" goto found_self
+set _SCRIPT_SELF=%_SCRIPT_SELF%.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+
+REM Determin a correct self - by current working directory.
+set _SCRIPT_SELF=%_SCRIPT_CURDIR%\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+
+REM Determin a correct self - by the PATH
+REM This is very verbose because nested for loops didn't work out.
+for /f "tokens=1 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=2 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=3 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=4 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=5 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=6 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=7 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=8 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=9 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=10 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=11 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=12 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=13 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=14 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=15 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=16 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=17 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=18 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=19 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+for /f "tokens=20 delims=;" %%d in ("%PATH%") do set _SCRIPT_SELF=%%d\comregister.cmd
+if exist "%_SCRIPT_SELF%" goto found_self
+echo Warning: Not able to determin the comregister.cmd location.
+set _VBOX_DIR=
+goto register
+
+:found_self
+set _VBOX_DIR=
+cd "%_SCRIPT_SELF%\.."
+for /f "tokens=*" %%d in ('cd') do set _VBOX_DIR=%%d\
+cd "%_SCRIPT_CURDIR%"
+
+
+REM
+REM Do the registrations.
+REM
+:register
+@echo on
+%_VBOX_DIR%VBoxSVC.exe /ReregServer
+regsvr32 /s /u %_VBOX_DIR%VBoxC.dll
+regsvr32 /s %_VBOX_DIR%VBoxC.dll
+@echo off
+
+:end
+endlocal
-REM /*
-REM * Script to register the VirtualBox COM classes
-REM * (both inproc and out-of-process)
-REM */
-
-REM /*
-REM Copyright (C) 2006-2007 Oracle Corporation
-REM
-REM This file is part of VirtualBox Open Source Edition (OSE), as
-REM available from http://www.virtualbox.org. This file is free software;
-REM you can redistribute it and/or modify it under the terms of the GNU
-REM General Public License (GPL) as published by the Free Software
-REM Foundation, in version 2 as it comes in the "COPYING" file of the
-REM VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-REM hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-REM
-REM */
-
-
-VBoxSVC.exe /ReregServer
-
-regsvr32 /s /u VBoxC.dll
-regsvr32 /s VBoxC.dll
diff --git a/src/VBox/Main/src-client/BusAssignmentManager.cpp b/src/VBox/Main/src-client/BusAssignmentManager.cpp
index e25b05e14..18e34741e 100644
--- a/src/VBox/Main/src-client/BusAssignmentManager.cpp
+++ b/src/VBox/Main/src-client/BusAssignmentManager.cpp
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -25,7 +25,7 @@
#include <VBox/com/array.h>
-#include "PciDeviceAttachmentImpl.h"
+#include "PCIDeviceAttachmentImpl.h"
#include <map>
#include <vector>
@@ -64,7 +64,6 @@ static const DeviceAssignmentRule aGenericRules[] =
{"hda", 0, 5, 0, 0},
/* Storage controllers */
- {"ahci", 0, 13, 0, 1},
{"lsilogic", 0, 20, 0, 1},
{"buslogic", 0, 21, 0, 1},
{"lsilogicsas", 0, 22, 0, 1},
@@ -100,6 +99,7 @@ static const DeviceAssignmentRule aGenericRules[] =
static const DeviceAssignmentRule aPiix3Rules[] =
{
{"piix3ide", 0, 1, 1, 0},
+ {"ahci", 0, 13, 0, 1},
{"pcibridge", 0, 24, 0, 0},
{"pcibridge", 0, 25, 0, 0},
{ NULL, -1, -1, -1, 0}
@@ -216,42 +216,42 @@ static const DeviceAliasRule aDeviceAliases[] =
struct BusAssignmentManager::State
{
- struct PciDeviceRecord
+ struct PCIDeviceRecord
{
char szDevName[32];
- PciBusAddress HostAddress;
+ PCIBusAddress HostAddress;
- PciDeviceRecord(const char* pszName, PciBusAddress aHostAddress)
+ PCIDeviceRecord(const char* pszName, PCIBusAddress aHostAddress)
{
RTStrCopy(this->szDevName, sizeof(szDevName), pszName);
this->HostAddress = aHostAddress;
}
- PciDeviceRecord(const char* pszName)
+ PCIDeviceRecord(const char* pszName)
{
RTStrCopy(this->szDevName, sizeof(szDevName), pszName);
}
- bool operator<(const PciDeviceRecord &a) const
+ bool operator<(const PCIDeviceRecord &a) const
{
return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) < 0;
}
- bool operator==(const PciDeviceRecord &a) const
+ bool operator==(const PCIDeviceRecord &a) const
{
return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) == 0;
}
};
- typedef std::map <PciBusAddress,PciDeviceRecord > PciMap;
- typedef std::vector<PciBusAddress> PciAddrList;
- typedef std::vector<const DeviceAssignmentRule*> PciRulesList;
- typedef std::map <PciDeviceRecord,PciAddrList > ReversePciMap;
+ typedef std::map <PCIBusAddress,PCIDeviceRecord > PCIMap;
+ typedef std::vector<PCIBusAddress> PCIAddrList;
+ typedef std::vector<const DeviceAssignmentRule*> PCIRulesList;
+ typedef std::map <PCIDeviceRecord,PCIAddrList > ReversePCIMap;
volatile int32_t cRefCnt;
ChipsetType_T mChipsetType;
- PciMap mPciMap;
- ReversePciMap mReversePciMap;
+ PCIMap mPCIMap;
+ ReversePCIMap mReversePCIMap;
State()
: cRefCnt(1), mChipsetType(ChipsetType_Null)
@@ -261,14 +261,14 @@ struct BusAssignmentManager::State
HRESULT init(ChipsetType_T chipsetType);
- HRESULT record(const char* pszName, PciBusAddress& GuestAddress, PciBusAddress HostAddress);
- HRESULT autoAssign(const char* pszName, PciBusAddress& Address);
- bool checkAvailable(PciBusAddress& Address);
- bool findPciAddress(const char* pszDevName, int iInstance, PciBusAddress& Address);
+ HRESULT record(const char* pszName, PCIBusAddress& GuestAddress, PCIBusAddress HostAddress);
+ HRESULT autoAssign(const char* pszName, PCIBusAddress& Address);
+ bool checkAvailable(PCIBusAddress& Address);
+ bool findPCIAddress(const char* pszDevName, int iInstance, PCIBusAddress& Address);
const char* findAlias(const char* pszName);
- void addMatchingRules(const char* pszName, PciRulesList& aList);
- void listAttachedPciDevices(ComSafeArrayOut(IPciDeviceAttachment*, aAttached));
+ void addMatchingRules(const char* pszName, PCIRulesList& aList);
+ void listAttachedPCIDevices(ComSafeArrayOut(IPCIDeviceAttachment*, aAttached));
};
HRESULT BusAssignmentManager::State::init(ChipsetType_T chipsetType)
@@ -277,18 +277,18 @@ HRESULT BusAssignmentManager::State::init(ChipsetType_T chipsetType)
return S_OK;
}
-HRESULT BusAssignmentManager::State::record(const char* pszName, PciBusAddress& Address, PciBusAddress HostAddress)
+HRESULT BusAssignmentManager::State::record(const char* pszName, PCIBusAddress& Address, PCIBusAddress HostAddress)
{
- PciDeviceRecord devRec(pszName, HostAddress);
+ PCIDeviceRecord devRec(pszName, HostAddress);
/* Remember address -> device mapping */
- mPciMap.insert(PciMap::value_type(Address, devRec));
+ mPCIMap.insert(PCIMap::value_type(Address, devRec));
- ReversePciMap::iterator it = mReversePciMap.find(devRec);
- if (it == mReversePciMap.end())
+ ReversePCIMap::iterator it = mReversePCIMap.find(devRec);
+ if (it == mReversePCIMap.end())
{
- mReversePciMap.insert(ReversePciMap::value_type(devRec, PciAddrList()));
- it = mReversePciMap.find(devRec);
+ mReversePCIMap.insert(ReversePCIMap::value_type(devRec, PCIAddrList()));
+ it = mReversePCIMap.find(devRec);
}
/* Remember device name -> addresses mapping */
@@ -297,12 +297,12 @@ HRESULT BusAssignmentManager::State::record(const char* pszName, PciBusAddress&
return S_OK;
}
-bool BusAssignmentManager::State::findPciAddress(const char* pszDevName, int iInstance, PciBusAddress& Address)
+bool BusAssignmentManager::State::findPCIAddress(const char* pszDevName, int iInstance, PCIBusAddress& Address)
{
- PciDeviceRecord devRec(pszDevName);
+ PCIDeviceRecord devRec(pszDevName);
- ReversePciMap::iterator it = mReversePciMap.find(devRec);
- if (it == mReversePciMap.end())
+ ReversePCIMap::iterator it = mReversePCIMap.find(devRec);
+ if (it == mReversePCIMap.end())
return false;
if (iInstance >= (int)it->second.size())
@@ -312,7 +312,7 @@ bool BusAssignmentManager::State::findPciAddress(const char* pszDevName, int
return true;
}
-void BusAssignmentManager::State::addMatchingRules(const char* pszName, PciRulesList& aList)
+void BusAssignmentManager::State::addMatchingRules(const char* pszName, PCIRulesList& aList)
{
size_t iRuleset, iRule;
const DeviceAssignmentRule* aArrays[2] = {aGenericRules, NULL};
@@ -358,9 +358,9 @@ static bool RuleComparator(const DeviceAssignmentRule* r1, const DeviceAssignme
return (r1->iPriority > r2->iPriority);
}
-HRESULT BusAssignmentManager::State::autoAssign(const char* pszName, PciBusAddress& Address)
+HRESULT BusAssignmentManager::State::autoAssign(const char* pszName, PCIBusAddress& Address)
{
- PciRulesList matchingRules;
+ PCIRulesList matchingRules;
addMatchingRules(pszName, matchingRules);
const char* pszAlias = findAlias(pszName);
@@ -387,21 +387,21 @@ HRESULT BusAssignmentManager::State::autoAssign(const char* pszName, PciBusAddre
return E_INVALIDARG;
}
-bool BusAssignmentManager::State::checkAvailable(PciBusAddress& Address)
+bool BusAssignmentManager::State::checkAvailable(PCIBusAddress& Address)
{
- PciMap::const_iterator it = mPciMap.find(Address);
+ PCIMap::const_iterator it = mPCIMap.find(Address);
- return (it == mPciMap.end());
+ return (it == mPCIMap.end());
}
-void BusAssignmentManager::State::listAttachedPciDevices(ComSafeArrayOut(IPciDeviceAttachment*, aAttached))
+void BusAssignmentManager::State::listAttachedPCIDevices(ComSafeArrayOut(IPCIDeviceAttachment*, aAttached))
{
- com::SafeIfaceArray<IPciDeviceAttachment> result(mPciMap.size());
+ com::SafeIfaceArray<IPCIDeviceAttachment> result(mPCIMap.size());
size_t iIndex = 0;
- ComObjPtr<PciDeviceAttachment> dev;
- for (PciMap::const_iterator it = mPciMap.begin(); it != mPciMap.end(); ++it)
+ ComObjPtr<PCIDeviceAttachment> dev;
+ for (PCIMap::const_iterator it = mPCIMap.begin(); it != mPCIMap.end(); ++it)
{
dev.createObject();
com::Bstr devname(it->second.szDevName);
@@ -457,10 +457,10 @@ DECLINLINE(HRESULT) InsertConfigInteger(PCFGMNODE pCfg, const char* pszName, ui
return S_OK;
}
-HRESULT BusAssignmentManager::assignPciDeviceImpl(const char* pszDevName,
+HRESULT BusAssignmentManager::assignPCIDeviceImpl(const char* pszDevName,
PCFGMNODE pCfg,
- PciBusAddress& GuestAddress,
- PciBusAddress HostAddress,
+ PCIBusAddress& GuestAddress,
+ PCIBusAddress HostAddress,
bool fGuestAddressRequired)
{
HRESULT rc = S_OK;
@@ -503,12 +503,12 @@ HRESULT BusAssignmentManager::assignPciDeviceImpl(const char* pszDevName,
}
-bool BusAssignmentManager::findPciAddress(const char* pszDevName, int iInstance, PciBusAddress& Address)
+bool BusAssignmentManager::findPCIAddress(const char* pszDevName, int iInstance, PCIBusAddress& Address)
{
- return pState->findPciAddress(pszDevName, iInstance, Address);
+ return pState->findPCIAddress(pszDevName, iInstance, Address);
}
-void BusAssignmentManager::listAttachedPciDevices(ComSafeArrayOut(IPciDeviceAttachment*, aAttached))
+void BusAssignmentManager::listAttachedPCIDevices(ComSafeArrayOut(IPCIDeviceAttachment*, aAttached))
{
- pState->listAttachedPciDevices(ComSafeArrayOutArg(aAttached));
+ pState->listAttachedPCIDevices(ComSafeArrayOutArg(aAttached));
}
diff --git a/src/VBox/Main/src-client/ConsoleImpl.cpp b/src/VBox/Main/src-client/ConsoleImpl.cpp
index 287e1d5e0..5102e7fbd 100644
--- a/src/VBox/Main/src-client/ConsoleImpl.cpp
+++ b/src/VBox/Main/src-client/ConsoleImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -56,6 +56,7 @@
#include "RemoteUSBDeviceImpl.h"
#include "SharedFolderImpl.h"
#include "AudioSnifferInterface.h"
+#include "Nvram.h"
#ifdef VBOX_WITH_USB_VIDEO
# include "UsbWebcamInterface.h"
#endif
@@ -65,14 +66,11 @@
#include "ProgressCombinedImpl.h"
#include "ConsoleVRDPServer.h"
#include "VMMDev.h"
-#include "package-generated.h"
#ifdef VBOX_WITH_EXTPACK
# include "ExtPackManagerImpl.h"
#endif
#include "BusAssignmentManager.h"
-// generated header
-#include "SchemaDefs.h"
#include "VBoxEvents.h"
#include "AutoCaller.h"
#include "Logging.h"
@@ -100,17 +98,20 @@
#ifdef VBOX_WITH_USB
# include <VBox/vmm/pdmusb.h>
#endif
+#ifdef VBOX_WITH_NETSHAPER
+# include <VBox/vmm/pdmnetshaper.h>
+#endif /* VBOX_WITH_NETSHAPER */
#include <VBox/vmm/mm.h>
#include <VBox/vmm/ftm.h>
#include <VBox/vmm/ssm.h>
#include <VBox/err.h>
#include <VBox/param.h>
#include <VBox/vusb.h>
-#include <VBox/version.h>
#include <VBox/VMMDev.h>
#include <VBox/HostServices/VBoxClipboardSvc.h>
+#include <VBox/HostServices/DragAndDropSvc.h>
#ifdef VBOX_WITH_GUEST_PROPS
# include <VBox/HostServices/GuestPropertySvc.h>
# include <VBox/com/array.h>
@@ -120,7 +121,6 @@
#include <algorithm>
#include <memory> // for auto_ptr
#include <vector>
-#include <typeinfo>
// VMTask and friends
@@ -325,9 +325,9 @@ public:
bool fUdp = (proto == NATProtocol_UDP);
Bstr hostIp, guestIp;
LONG hostPort, guestPort;
- pNREv->COMGETTER(HostIp)(hostIp.asOutParam());
+ pNREv->COMGETTER(HostIP)(hostIp.asOutParam());
pNREv->COMGETTER(HostPort)(&hostPort);
- pNREv->COMGETTER(GuestIp)(guestIp.asOutParam());
+ pNREv->COMGETTER(GuestIP)(guestIp.asOutParam());
pNREv->COMGETTER(GuestPort)(&guestPort);
ULONG ulSlot;
rc = pNREv->COMGETTER(Slot)(&ulSlot);
@@ -338,7 +338,7 @@ public:
}
break;
- case VBoxEventType_OnHostPciDevicePlug:
+ case VBoxEventType_OnHostPCIDevicePlug:
{
// handle if needed
break;
@@ -377,6 +377,7 @@ Console::Console()
, mpVmm2UserMethods(NULL)
, m_pVMMDev(NULL)
, mAudioSniffer(NULL)
+ , mNvram(NULL)
#ifdef VBOX_WITH_USB_VIDEO
, mUsbWebcamInterface(NULL)
#endif
@@ -388,8 +389,6 @@ Console::Console()
, mfUseHostClipboard(true)
, mMachineState(MachineState_PoweredOff)
{
- for (ULONG slot = 0; slot < SchemaDefs::NetworkAdapterCount; ++slot)
- meAttachmentType[slot] = NetworkAttachmentType_Null;
}
Console::~Console()
@@ -404,7 +403,7 @@ HRESULT Console::FinalConstruct()
memset(&mapUSBLed, 0, sizeof(mapUSBLed));
memset(&mapSharedFolderLed, 0, sizeof(mapSharedFolderLed));
- for (unsigned i = 0; i < RT_ELEMENTS(maStorageDevType); ++ i)
+ for (unsigned i = 0; i < RT_ELEMENTS(maStorageDevType); ++i)
maStorageDevType[i] = DeviceType_Null;
MYVMM2USERMETHODS *pVmm2UserMethods = (MYVMM2USERMETHODS *)RTMemAllocZ(sizeof(*mpVmm2UserMethods) + sizeof(Console *));
@@ -436,7 +435,7 @@ void Console::FinalRelease()
// public initializer/uninitializer for internal purposes only
/////////////////////////////////////////////////////////////////////////////
-HRESULT Console::init(IMachine *aMachine, IInternalMachineControl *aControl)
+HRESULT Console::init(IMachine *aMachine, IInternalMachineControl *aControl, LockType_T aLockType)
{
AssertReturn(aMachine && aControl, E_INVALIDARG);
@@ -452,104 +451,129 @@ HRESULT Console::init(IMachine *aMachine, IInternalMachineControl *aControl)
unconst(mMachine) = aMachine;
unconst(mControl) = aControl;
- /* Cache essential properties and objects */
+ /* Cache essential properties and objects, and create child objects */
rc = mMachine->COMGETTER(State)(&mMachineState);
AssertComRCReturnRC(rc);
- rc = mMachine->COMGETTER(VRDEServer)(unconst(mVRDEServer).asOutParam());
- AssertComRCReturnRC(rc);
-
- /* Create associated child COM objects */
+#ifdef VBOX_WITH_EXTPACK
+ unconst(mptrExtPackManager).createObject();
+ rc = mptrExtPackManager->initExtPackManager(NULL, VBOXEXTPACKCTX_VM_PROCESS);
+ AssertComRCReturnRC(rc);
+#endif
// Event source may be needed by other children
unconst(mEventSource).createObject();
rc = mEventSource->init(static_cast<IConsole*>(this));
AssertComRCReturnRC(rc);
- unconst(mGuest).createObject();
- rc = mGuest->init(this);
- AssertComRCReturnRC(rc);
+ mcAudioRefs = 0;
+ mcVRDPClients = 0;
+ mu32SingleRDPClientId = 0;
+ mcGuestCredentialsProvided = false;
- unconst(mKeyboard).createObject();
- rc = mKeyboard->init(this);
- AssertComRCReturnRC(rc);
+ /* Now the VM specific parts */
+ if (aLockType == LockType_VM)
+ {
+ rc = mMachine->COMGETTER(VRDEServer)(unconst(mVRDEServer).asOutParam());
+ AssertComRCReturnRC(rc);
- unconst(mMouse).createObject();
- rc = mMouse->init(this);
- AssertComRCReturnRC(rc);
+ unconst(mGuest).createObject();
+ rc = mGuest->init(this);
+ AssertComRCReturnRC(rc);
- unconst(mDisplay).createObject();
- rc = mDisplay->init(this);
- AssertComRCReturnRC(rc);
+ unconst(mKeyboard).createObject();
+ rc = mKeyboard->init(this);
+ AssertComRCReturnRC(rc);
- unconst(mVRDEServerInfo).createObject();
- rc = mVRDEServerInfo->init(this);
- AssertComRCReturnRC(rc);
+ unconst(mMouse).createObject();
+ rc = mMouse->init(this);
+ AssertComRCReturnRC(rc);
-#ifdef VBOX_WITH_EXTPACK
- unconst(mptrExtPackManager).createObject();
- rc = mptrExtPackManager->initExtPackManager(NULL, VBOXEXTPACKCTX_VM_PROCESS);
- AssertComRCReturnRC(rc);
-#endif
+ unconst(mDisplay).createObject();
+ rc = mDisplay->init(this);
+ AssertComRCReturnRC(rc);
- /* Grab global and machine shared folder lists */
+ unconst(mVRDEServerInfo).createObject();
+ rc = mVRDEServerInfo->init(this);
+ AssertComRCReturnRC(rc);
- rc = fetchSharedFolders(true /* aGlobal */);
- AssertComRCReturnRC(rc);
- rc = fetchSharedFolders(false /* aGlobal */);
- AssertComRCReturnRC(rc);
+ /* Grab global and machine shared folder lists */
- /* Create other child objects */
+ rc = fetchSharedFolders(true /* aGlobal */);
+ AssertComRCReturnRC(rc);
+ rc = fetchSharedFolders(false /* aGlobal */);
+ AssertComRCReturnRC(rc);
- unconst(mConsoleVRDPServer) = new ConsoleVRDPServer(this);
- AssertReturn(mConsoleVRDPServer, E_FAIL);
+ /* Create other child objects */
- mcAudioRefs = 0;
- mcVRDPClients = 0;
- mu32SingleRDPClientId = 0;
- mcGuestCredentialsProvided = false;
+ unconst(mConsoleVRDPServer) = new ConsoleVRDPServer(this);
+ AssertReturn(mConsoleVRDPServer, E_FAIL);
- // VirtualBox 4.0: We no longer initialize the VMMDev instance here,
- // which starts the HGCM thread. Instead, this is now done in the
- // power-up thread when a VM is actually being powered up to avoid
- // having HGCM threads all over the place every time a session is
- // opened, even if that session will not run a VM.
- // unconst(m_pVMMDev) = new VMMDev(this);
- // AssertReturn(mVMMDev, E_FAIL);
+ /* Figure out size of meAttachmentType vector */
+ ComPtr<IVirtualBox> pVirtualBox;
+ rc = aMachine->COMGETTER(Parent)(pVirtualBox.asOutParam());
+ AssertComRC(rc);
+ ComPtr<ISystemProperties> pSystemProperties;
+ if (pVirtualBox)
+ pVirtualBox->COMGETTER(SystemProperties)(pSystemProperties.asOutParam());
+ ChipsetType_T chipsetType = ChipsetType_PIIX3;
+ aMachine->COMGETTER(ChipsetType)(&chipsetType);
+ ULONG maxNetworkAdapters = 0;
+ if (pSystemProperties)
+ pSystemProperties->GetMaxNetworkAdapters(chipsetType, &maxNetworkAdapters);
+ meAttachmentType.resize(maxNetworkAdapters);
+ for (ULONG slot = 0; slot < maxNetworkAdapters; ++slot)
+ meAttachmentType[slot] = NetworkAttachmentType_Null;
+
+ // VirtualBox 4.0: We no longer initialize the VMMDev instance here,
+ // which starts the HGCM thread. Instead, this is now done in the
+ // power-up thread when a VM is actually being powered up to avoid
+ // having HGCM threads all over the place every time a session is
+ // opened, even if that session will not run a VM.
+ // unconst(m_pVMMDev) = new VMMDev(this);
+ // AssertReturn(mVMMDev, E_FAIL);
+
+ unconst(mAudioSniffer) = new AudioSniffer(this);
+ AssertReturn(mAudioSniffer, E_FAIL);
+
+ FirmwareType_T enmFirmwareType;
+ mMachine->COMGETTER(FirmwareType)(&enmFirmwareType);
+ if ( enmFirmwareType == FirmwareType_EFI
+ || enmFirmwareType == FirmwareType_EFI32
+ || enmFirmwareType == FirmwareType_EFI64
+ || enmFirmwareType == FirmwareType_EFIDUAL)
+ {
+ unconst(mNvram) = new Nvram(this);
+ AssertReturn(mNvram, E_FAIL);
+ }
- unconst(mAudioSniffer) = new AudioSniffer(this);
- AssertReturn(mAudioSniffer, E_FAIL);
#ifdef VBOX_WITH_USB_VIDEO
- unconst(mUsbWebcamInterface) = new UsbWebcamInterface(this);
- AssertReturn(mUsbWebcamInterface, E_FAIL);
+ unconst(mUsbWebcamInterface) = new UsbWebcamInterface(this);
+ AssertReturn(mUsbWebcamInterface, E_FAIL);
#endif
#ifdef VBOX_WITH_USB_CARDREADER
- unconst(mUsbCardReader) = new UsbCardReader(this);
- AssertReturn(mUsbCardReader, E_FAIL);
+ unconst(mUsbCardReader) = new UsbCardReader(this);
+ AssertReturn(mUsbCardReader, E_FAIL);
#endif
- /* VirtualBox events registration. */
- {
- ComPtr<IVirtualBox> pVirtualBox;
- rc = aMachine->COMGETTER(Parent)(pVirtualBox.asOutParam());
- AssertComRC(rc);
-
- ComPtr<IEventSource> pES;
- rc = pVirtualBox->COMGETTER(EventSource)(pES.asOutParam());
- AssertComRC(rc);
- ComObjPtr<VmEventListenerImpl> aVmListener;
- aVmListener.createObject();
- aVmListener->init(new VmEventListener(), this);
- mVmListener = aVmListener;
- com::SafeArray<VBoxEventType_T> eventTypes;
- eventTypes.push_back(VBoxEventType_OnNATRedirect);
- eventTypes.push_back(VBoxEventType_OnHostPciDevicePlug);
- rc = pES->RegisterListener(aVmListener, ComSafeArrayAsInParam(eventTypes), true);
- AssertComRC(rc);
+ /* VirtualBox events registration. */
+ {
+ ComPtr<IEventSource> pES;
+ rc = pVirtualBox->COMGETTER(EventSource)(pES.asOutParam());
+ AssertComRC(rc);
+ ComObjPtr<VmEventListenerImpl> aVmListener;
+ aVmListener.createObject();
+ aVmListener->init(new VmEventListener(), this);
+ mVmListener = aVmListener;
+ com::SafeArray<VBoxEventType_T> eventTypes;
+ eventTypes.push_back(VBoxEventType_OnNATRedirect);
+ eventTypes.push_back(VBoxEventType_OnHostPCIDevicePlug);
+ rc = pES->RegisterListener(aVmListener, ComSafeArrayAsInParam(eventTypes), true);
+ AssertComRC(rc);
+ }
}
-
/* Confirm a successful initialization when it's the case */
autoInitSpan.setSucceeded();
@@ -619,6 +643,12 @@ void Console::uninit()
mpVmm2UserMethods = NULL;
}
+ if (mNvram)
+ {
+ delete mNvram;
+ unconst(mNvram) = NULL;
+ }
+
#ifdef VBOX_WITH_USB_VIDEO
if (mUsbWebcamInterface)
{
@@ -664,7 +694,7 @@ void Console::uninit()
if (mVRDEServerInfo)
{
mVRDEServerInfo->uninit();
- unconst(mVRDEServerInfo).setNull();;
+ unconst(mVRDEServerInfo).setNull();
}
if (mDebugger)
@@ -688,13 +718,13 @@ void Console::uninit()
if (mKeyboard)
{
mKeyboard->uninit();
- unconst(mKeyboard).setNull();;
+ unconst(mKeyboard).setNull();
}
if (mGuest)
{
mGuest->uninit();
- unconst(mGuest).setNull();;
+ unconst(mGuest).setNull();
}
if (mConsoleVRDPServer)
@@ -711,7 +741,9 @@ void Console::uninit()
// we don't perform uninit() as it's possible that some pending event refers to this source
unconst(mEventSource).setNull();
+#ifdef CONSOLE_WITH_EVENT_CACHE
mCallbackData.clear();
+#endif
LogFlowThisFuncLeave();
}
@@ -844,6 +876,63 @@ void Console::guestPropertiesVRDPUpdateNameChange(uint32_t u32ClientId, const ch
}
+void Console::guestPropertiesVRDPUpdateIPAddrChange(uint32_t u32ClientId, const char *pszIPAddr)
+{
+ if (!guestPropertiesVRDPEnabled())
+ return;
+
+ LogFlowFunc(("\n"));
+
+ char szPropNm[256];
+ Bstr bstrReadOnlyGuest(L"RDONLYGUEST");
+
+ RTStrPrintf(szPropNm, sizeof(szPropNm), "/VirtualBox/HostInfo/VRDP/Client/%u/IPAddr", u32ClientId);
+ Bstr clientIPAddr(pszIPAddr);
+
+ mMachine->SetGuestProperty(Bstr(szPropNm).raw(),
+ clientIPAddr.raw(),
+ bstrReadOnlyGuest.raw());
+
+}
+
+void Console::guestPropertiesVRDPUpdateLocationChange(uint32_t u32ClientId, const char *pszLocation)
+{
+ if (!guestPropertiesVRDPEnabled())
+ return;
+
+ LogFlowFunc(("\n"));
+
+ char szPropNm[256];
+ Bstr bstrReadOnlyGuest(L"RDONLYGUEST");
+
+ RTStrPrintf(szPropNm, sizeof(szPropNm), "/VirtualBox/HostInfo/VRDP/Client/%u/Location", u32ClientId);
+ Bstr clientLocation(pszLocation);
+
+ mMachine->SetGuestProperty(Bstr(szPropNm).raw(),
+ clientLocation.raw(),
+ bstrReadOnlyGuest.raw());
+
+}
+
+void Console::guestPropertiesVRDPUpdateOtherInfoChange(uint32_t u32ClientId, const char *pszOtherInfo)
+{
+ if (!guestPropertiesVRDPEnabled())
+ return;
+
+ LogFlowFunc(("\n"));
+
+ char szPropNm[256];
+ Bstr bstrReadOnlyGuest(L"RDONLYGUEST");
+
+ RTStrPrintf(szPropNm, sizeof(szPropNm), "/VirtualBox/HostInfo/VRDP/Client/%u/OtherInfo", u32ClientId);
+ Bstr clientOtherInfo(pszOtherInfo);
+
+ mMachine->SetGuestProperty(Bstr(szPropNm).raw(),
+ clientOtherInfo.raw(),
+ bstrReadOnlyGuest.raw());
+
+}
+
void Console::guestPropertiesVRDPUpdateClientAttach(uint32_t u32ClientId, bool fAttached)
{
if (!guestPropertiesVRDPEnabled())
@@ -1171,6 +1260,18 @@ void Console::VRDPClientStatusChange(uint32_t u32ClientId, const char *pszStatus
{
guestPropertiesVRDPUpdateNameChange(u32ClientId, pszStatus + strlen("NAME="));
}
+ else if (RTStrNICmp(pszStatus, "CIPA=", strlen("CIPA=")) == 0)
+ {
+ guestPropertiesVRDPUpdateIPAddrChange(u32ClientId, pszStatus + strlen("CIPA="));
+ }
+ else if (RTStrNICmp(pszStatus, "CLOCATION=", strlen("CLOCATION=")) == 0)
+ {
+ guestPropertiesVRDPUpdateLocationChange(u32ClientId, pszStatus + strlen("CLOCATION="));
+ }
+ else if (RTStrNICmp(pszStatus, "COINFO=", strlen("COINFO=")) == 0)
+ {
+ guestPropertiesVRDPUpdateOtherInfoChange(u32ClientId, pszStatus + strlen("COINFO="));
+ }
#endif
LogFlowFuncLeave();
@@ -1449,7 +1550,7 @@ Console::saveStateFileExec(PSSMHANDLE pSSM, void *pvUser)
for (SharedFolderMap::const_iterator it = that->m_mapSharedFolders.begin();
it != that->m_mapSharedFolders.end();
- ++ it)
+ ++it)
{
SharedFolder *pSF = (*it).second;
AutoCaller sfCaller(pSF);
@@ -1529,7 +1630,7 @@ Console::loadStateFileExecInternal(PSSMHANDLE pSSM, uint32_t u32Version)
int vrc = SSMR3GetU32(pSSM, &size);
AssertRCReturn(vrc, vrc);
- for (uint32_t i = 0; i < size; ++ i)
+ for (uint32_t i = 0; i < size; ++i)
{
Utf8Str strName;
Utf8Str strHostPath;
@@ -1900,15 +2001,17 @@ STDMETHODIMP Console::COMGETTER(EventSource)(IEventSource ** aEventSource)
CheckComArgOutPointerValid(aEventSource);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- // no need to lock - lifetime constant
- mEventSource.queryInterfaceTo(aEventSource);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ // no need to lock - lifetime constant
+ mEventSource.queryInterfaceTo(aEventSource);
+ }
- return S_OK;
+ return hrc;
}
-STDMETHODIMP Console::COMGETTER(AttachedPciDevices)(ComSafeArrayOut(IPciDeviceAttachment *, aAttachments))
+STDMETHODIMP Console::COMGETTER(AttachedPCIDevices)(ComSafeArrayOut(IPCIDeviceAttachment *, aAttachments))
{
CheckComArgOutSafeArrayPointerValid(aAttachments);
@@ -1918,10 +2021,10 @@ STDMETHODIMP Console::COMGETTER(AttachedPciDevices)(ComSafeArrayOut(IPciDeviceAt
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
if (mBusMgr)
- mBusMgr->listAttachedPciDevices(ComSafeArrayOutArg(aAttachments));
+ mBusMgr->listAttachedPCIDevices(ComSafeArrayOutArg(aAttachments));
else
{
- com::SafeIfaceArray<IPciDeviceAttachment> result((size_t)0);
+ com::SafeIfaceArray<IPCIDeviceAttachment> result((size_t)0);
result.detachTo(ComSafeArrayOutArg(aAttachments));
}
@@ -2062,7 +2165,7 @@ STDMETHODIMP Console::PowerDown(IProgress **aProgress)
int vrc = RTThreadCreate(NULL, Console::powerDownThread,
(void *) task.get(), 0,
RTTHREADTYPE_MAIN_WORKER, 0,
- "VMPowerDown");
+ "VMPwrDwn");
if (RT_FAILURE(vrc))
{
rc = setError(E_FAIL, "Could not create VMPowerDown thread (%Rrc)", vrc);
@@ -2122,8 +2225,8 @@ STDMETHODIMP Console::Reset()
if (!ptrVM.isOk())
return ptrVM.rc();
- /* leave the lock before a VMR3* call (EMT will call us back)! */
- alock.leave();
+ /* release the lock before a VMR3* call (EMT will call us back)! */
+ alock.release();
int vrc = VMR3Reset(ptrVM);
@@ -2335,7 +2438,7 @@ HRESULT Console::doCPUAdd(ULONG aCpu, PVM pVM)
(PFNRT)Console::plugCpu, 3,
this, pVM, aCpu);
- /* leave the lock before a VMR3* call (EMT will call us back)! */
+ /* release the lock before a VMR3* call (EMT will call us back)! */
alock.release();
if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
@@ -2399,8 +2502,8 @@ STDMETHODIMP Console::Pause()
LogFlowThisFunc(("Sending PAUSE request...\n"));
- /* leave the lock before a VMR3* call (EMT will call us back)! */
- alock.leave();
+ /* release the lock before a VMR3* call (EMT will call us back)! */
+ alock.release();
int vrc = VMR3Suspend(ptrVM);
@@ -2434,8 +2537,8 @@ STDMETHODIMP Console::Resume()
LogFlowThisFunc(("Sending RESUME request...\n"));
- /* leave the lock before a VMR3* call (EMT will call us back)! */
- alock.leave();
+ /* release the lock before a VMR3* call (EMT will call us back)! */
+ alock.release();
#ifdef VBOX_WITH_EXTPACK
int vrc = mptrExtPackManager->callAllVmPowerOnHooks(this, ptrVM); /** @todo called a few times too many... */
@@ -2479,7 +2582,8 @@ STDMETHODIMP Console::PowerButton()
SafeVMPtr ptrVM(this);
if (!ptrVM.isOk())
return ptrVM.rc();
-/** @todo leave the console lock? */
+
+ // no need to release lock, as there are no cross-thread callbacks
/* get the acpi device interface and press the button. */
PPDMIBASE pBase;
@@ -2526,7 +2630,8 @@ STDMETHODIMP Console::GetPowerButtonHandled(BOOL *aHandled)
SafeVMPtr ptrVM(this);
if (!ptrVM.isOk())
return ptrVM.rc();
-/** @todo leave the console lock? */
+
+ // no need to release lock, as there are no cross-thread callbacks
/* get the acpi device interface and check if the button press was handled. */
PPDMIBASE pBase;
@@ -2581,7 +2686,7 @@ STDMETHODIMP Console::GetGuestEnteredACPIMode(BOOL *aEntered)
if (!ptrVM.isOk())
return ptrVM.rc();
-/** @todo leave the console lock? */
+ // no need to release lock, as there are no cross-thread callbacks
/* get the acpi device interface and query the information. */
PPDMIBASE pBase;
@@ -2622,7 +2727,7 @@ STDMETHODIMP Console::SleepButton()
if (!ptrVM.isOk())
return ptrVM.rc();
-/** @todo leave the console lock? */
+ // no need to release lock, as there are no cross-thread callbacks
/* get the acpi device interface and press the sleep button. */
PPDMIBASE pBase;
@@ -2672,9 +2777,21 @@ STDMETHODIMP Console::SaveState(IProgress **aProgress)
if (mMachineState == MachineState_Running)
{
- HRESULT rc = Pause();
- if (FAILED(rc))
- return rc;
+ /* get the VM handle. */
+ SafeVMPtr ptrVM(this);
+ if (!ptrVM.isOk())
+ return ptrVM.rc();
+
+ /* release the lock before a VMR3* call (EMT will call us back)! */
+ alock.release();
+ int vrc = VMR3Suspend(ptrVM);
+ alock.acquire();
+
+ HRESULT hrc = S_OK;
+ if (RT_FAILURE(vrc))
+ hrc = setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc);
+ if (FAILED(hrc))
+ return hrc;
}
HRESULT rc = S_OK;
@@ -2725,7 +2842,7 @@ STDMETHODIMP Console::SaveState(IProgress **aProgress)
rc = task->rc();
/*
* If we fail here it means a PowerDown() call happened on another
- * thread while we were doing Pause() (which leaves the Console lock).
+ * thread while we were doing Pause() (which releases the Console lock).
* We assign PowerDown() a higher precedence than SaveState(),
* therefore just return the error to the caller.
*/
@@ -2771,7 +2888,13 @@ STDMETHODIMP Console::SaveState(IProgress **aProgress)
/* restore the paused state if appropriate */
setMachineStateLocally(MachineState_Paused);
/* restore the running state if appropriate */
- Resume();
+ SafeVMPtr ptrVM(this);
+ if (ptrVM.isOk())
+ {
+ alock.release();
+ VMR3Resume(ptrVM);
+ alock.acquire();
+ }
}
else
setMachineStateLocally(lastMachineState);
@@ -2826,7 +2949,7 @@ STDMETHODIMP Console::DiscardSavedState(BOOL aRemoveFile)
return rc;
}
-/** read the value of a LEd. */
+/** read the value of a LED. */
inline uint32_t readAndClearLed(PPDMLED pLed)
{
if (!pLed)
@@ -2933,9 +3056,9 @@ STDMETHODIMP Console::AttachUSBDevice(IN_BSTR aId)
return setError(VBOX_E_PDM_ERROR,
tr("The virtual machine does not have a USB controller"));
- /* leave the lock because the USB Proxy service may call us back
+ /* release the lock because the USB Proxy service may call us back
* (via onUSBDeviceAttach()) */
- alock.leave();
+ alock.release();
/* Request the device capture */
return mControl->CaptureUSBDevice(aId);
@@ -2967,7 +3090,7 @@ STDMETHODIMP Console::DetachUSBDevice(IN_BSTR aId, IUSBDevice **aDevice)
pUSBDevice = *it;
break;
}
- ++ it;
+ ++it;
}
if (!pUSBDevice)
@@ -2975,28 +3098,36 @@ STDMETHODIMP Console::DetachUSBDevice(IN_BSTR aId, IUSBDevice **aDevice)
tr("USB device with UUID {%RTuuid} is not attached to this machine"),
Guid(aId).raw());
+ /* Remove the device from the collection, it is re-added below for failures */
+ mUSBDevices.erase(it);
+
/*
* Inform the USB device and USB proxy about what's cooking.
*/
- alock.leave();
- HRESULT rc2 = mControl->DetachUSBDevice(aId, false /* aDone */);
- if (FAILED(rc2))
- return rc2;
- alock.enter();
+ alock.release();
+ HRESULT rc = mControl->DetachUSBDevice(aId, false /* aDone */);
+ if (FAILED(rc))
+ {
+ /* Re-add the device to the collection */
+ alock.acquire();
+ mUSBDevices.push_back(pUSBDevice);
+ return rc;
+ }
/* Request the PDM to detach the USB device. */
- HRESULT rc = detachUSBDevice(it);
-
+ rc = detachUSBDevice(pUSBDevice);
if (SUCCEEDED(rc))
{
- /* leave the lock since we don't need it any more (note though that
- * the USB Proxy service must not call us back here) */
- alock.leave();
-
/* Request the device release. Even if it fails, the device will
* remain as held by proxy, which is OK for us (the VM process). */
rc = mControl->DetachUSBDevice(aId, true /* aDone */);
}
+ else
+ {
+ /* Re-add the device to the collection */
+ alock.acquire();
+ mUSBDevices.push_back(pUSBDevice);
+ }
return rc;
@@ -3148,7 +3279,8 @@ Console::CreateSharedFolder(IN_BSTR aName, IN_BSTR aHostPath, BOOL aWritable, BO
m_mapSharedFolders.insert(std::make_pair(aName, pSharedFolder));
- /* notify console callbacks after the folder is added to the list */
+ /* Notify console callbacks after the folder is added to the list. */
+ alock.release();
fireSharedFolderChangedEvent(mEventSource, Scope_Session);
LogFlowThisFunc(("Leaving for '%ls' -> '%ls'\n", aName, aHostPath));
@@ -3213,7 +3345,8 @@ STDMETHODIMP Console::RemoveSharedFolder(IN_BSTR aName)
m_mapSharedFolders.erase(strName);
- /* notify console callbacks after the folder is removed to the list */
+ /* Notify console callbacks after the folder is removed from the list. */
+ alock.release();
fireSharedFolderChangedEvent(mEventSource, Scope_Session);
LogFlowThisFunc(("Leaving for '%ls'\n", aName));
@@ -3290,9 +3423,10 @@ STDMETHODIMP Console::TakeSnapshot(IN_BSTR aName,
// finally, create the progress object
ComObjPtr<Progress> pProgress;
pProgress.createObject();
- rc = pProgress->init(static_cast<IConsole*>(this),
+ rc = pProgress->init(static_cast<IConsole *>(this),
Bstr(tr("Taking a snapshot of the virtual machine")).raw(),
- mMachineState == MachineState_Running /* aCancelable */,
+ (mMachineState >= MachineState_FirstOnline)
+ && (mMachineState <= MachineState_LastOnline) /* aCancelable */,
cOperations,
ulTotalOperationsWeight,
Bstr(tr("Setting up snapshot operation")).raw(), // first sub-op description
@@ -3313,7 +3447,7 @@ STDMETHODIMP Console::TakeSnapshot(IN_BSTR aName,
/*
* If we fail here it means a PowerDown() call happened on another
- * thread while we were doing Pause() (which leaves the Console lock).
+ * thread while we were doing Pause() (which releases the Console lock).
* We assign PowerDown() a higher precedence than TakeSnapshot(),
* therefore just return the error to the caller.
*/
@@ -3332,7 +3466,7 @@ STDMETHODIMP Console::TakeSnapshot(IN_BSTR aName,
0,
RTTHREADTYPE_MAIN_WORKER,
0,
- "ConsoleTakeSnap");
+ "TakeSnap");
if (FAILED(vrc))
throw setError(E_FAIL,
tr("Could not create VMTakeSnap thread (%Rrc)"),
@@ -3468,36 +3602,6 @@ HRESULT Console::setInvalidMachineStateError()
}
-/**
- * @copydoc VirtualBox::handleUnexpectedExceptions
- */
-/* static */
-HRESULT Console::handleUnexpectedExceptions(RT_SRC_POS_DECL)
-{
- try
- {
- /* re-throw the current exception */
- throw;
- }
- catch (const std::exception &err)
- {
- return setErrorStatic(E_FAIL,
- tr("Unexpected exception: %s [%s]\n%s[%d] (%s)"),
- err.what(), typeid(err).name(),
- pszFile, iLine, pszFunction);
- }
- catch (...)
- {
- return setErrorStatic(E_FAIL,
- tr("Unknown exception\n%s[%d] (%s)"),
- pszFile, iLine, pszFunction);
- }
-
- /* should not get here */
- AssertFailed();
- return E_FAIL;
-}
-
/* static */
const char *Console::convertControllerTypeToDev(StorageControllerType_T enmCtrlType)
{
@@ -3639,8 +3743,8 @@ HRESULT Console::doMediumChange(IMediumAttachment *aMediumAttachment, bool fForc
aMediumAttachment,
fForce);
- /* leave the lock before waiting for a result (EMT will call us back!) */
- alock.leave();
+ /* release the lock before waiting for a result (EMT will call us back!) */
+ alock.release();
if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
{
@@ -3760,7 +3864,7 @@ DECLCALLBACK(int) Console::changeRemovableMedium(Console *pConsole,
enmBus,
fUseHostIOCache,
false /* fSetupMerge */,
- false /* fBuiltinIoCache */,
+ false /* fBuiltinIOCache */,
0 /* uMergeSource */,
0 /* uMergeTarget */,
aMediumAtt,
@@ -3892,8 +3996,8 @@ HRESULT Console::doStorageDeviceAttach(IMediumAttachment *aMediumAttachment, PVM
fUseHostIOCache,
aMediumAttachment);
- /* leave the lock before waiting for a result (EMT will call us back!) */
- alock.leave();
+ /* release the lock before waiting for a result (EMT will call us back!) */
+ alock.release();
if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
{
@@ -4005,7 +4109,7 @@ DECLCALLBACK(int) Console::attachStorageDevice(Console *pConsole,
enmBus,
fUseHostIOCache,
false /* fSetupMerge */,
- false /* fBuiltinIoCache */,
+ false /* fBuiltinIOCache */,
0 /* uMergeSource */,
0 /* uMergeTarget */,
aMediumAtt,
@@ -4133,8 +4237,8 @@ HRESULT Console::doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PVM
enmBus,
aMediumAttachment);
- /* leave the lock before waiting for a result (EMT will call us back!) */
- alock.leave();
+ /* release the lock before waiting for a result (EMT will call us back!) */
+ alock.release();
if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
{
@@ -4347,6 +4451,10 @@ HRESULT Console::onNetworkAdapterChange(INetworkAdapter *aNetworkAdapter, BOOL c
rc = aNetworkAdapter->COMGETTER(AdapterType)(&adapterType);
AssertComRC(rc);
const char *pszAdapterName = networkAdapterTypeToName(adapterType);
+
+ // prevent cross-thread deadlocks, don't need the lock any more
+ alock.release();
+
PPDMIBASE pBase;
int vrc = PDMR3QueryDeviceLun(ptrVM, pszAdapterName, ulInstance, 0, &pBase);
if (RT_SUCCESS(vrc))
@@ -4393,11 +4501,16 @@ HRESULT Console::onNetworkAdapterChange(INetworkAdapter *aNetworkAdapter, BOOL c
if (RT_FAILURE(vrc))
rc = E_FAIL;
+
+ alock.acquire();
}
}
ptrVM.release();
}
+ // definitely don't need the lock any more
+ alock.release();
+
/* notify console callbacks on success */
if (SUCCEEDED(rc))
fireNetworkAdapterChangedEvent(mEventSource, aNetworkAdapter);
@@ -4412,7 +4525,7 @@ HRESULT Console::onNetworkAdapterChange(INetworkAdapter *aNetworkAdapter, BOOL c
* @note Locks this object for writing.
*/
HRESULT Console::onNATRedirectRuleChange(ULONG ulInstance, BOOL aNatRuleRemove,
- NATProtocol_T aProto, IN_BSTR aHostIp, LONG aHostPort, IN_BSTR aGuestIp, LONG aGuestPort)
+ NATProtocol_T aProto, IN_BSTR aHostIP, LONG aHostPort, IN_BSTR aGuestIP, LONG aGuestPort)
{
LogFlowThisFunc(("\n"));
@@ -4483,7 +4596,7 @@ HRESULT Console::onNATRedirectRuleChange(ULONG ulInstance, BOOL aNatRuleRemove,
bool fUdp = aProto == NATProtocol_UDP;
vrc = pNetNatCfg->pfnRedirectRuleCommand(pNetNatCfg, !!aNatRuleRemove, fUdp,
- Utf8Str(aHostIp).c_str(), aHostPort, Utf8Str(aGuestIp).c_str(),
+ Utf8Str(aHostIP).c_str(), aHostPort, Utf8Str(aGuestIP).c_str(),
aGuestPort);
if (RT_FAILURE(vrc))
rc = E_FAIL;
@@ -4506,8 +4619,6 @@ HRESULT Console::onNATRedirectRuleChange(ULONG ulInstance, BOOL aNatRuleRemove,
* @param uInstance The PDM device instance.
* @param uLun The PDM LUN number of the drive.
* @param aNetworkAdapter The network adapter whose attachment needs to be changed
- *
- * @note Locks this object for writing.
*/
HRESULT Console::doNetworkAdapterChange(PVM pVM,
const char *pszDevice,
@@ -4521,9 +4632,6 @@ HRESULT Console::doNetworkAdapterChange(PVM pVM,
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
- /* We will need to release the write lock before calling EMT */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
/* Get the VM handle. */
SafeVMPtr ptrVM(this);
if (!ptrVM.isOk())
@@ -4539,9 +4647,6 @@ HRESULT Console::doNetworkAdapterChange(PVM pVM,
(PFNRT) Console::changeNetworkAttachment, 6,
this, ptrVM.raw(), pszDevice, uInstance, uLun, aNetworkAdapter);
- /* leave the lock before waiting for a result (EMT will call us back!) */
- alock.leave();
-
if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
{
vrc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
@@ -4590,17 +4695,27 @@ DECLCALLBACK(int) Console::changeNetworkAttachment(Console *pThis,
AssertReturn(pThis, VERR_INVALID_PARAMETER);
+ AutoCaller autoCaller(pThis);
+ AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
+
+ ComPtr<IVirtualBox> pVirtualBox;
+ pThis->mMachine->COMGETTER(Parent)(pVirtualBox.asOutParam());
+ ComPtr<ISystemProperties> pSystemProperties;
+ if (pVirtualBox)
+ pVirtualBox->COMGETTER(SystemProperties)(pSystemProperties.asOutParam());
+ ChipsetType_T chipsetType = ChipsetType_PIIX3;
+ pThis->mMachine->COMGETTER(ChipsetType)(&chipsetType);
+ ULONG maxNetworkAdapters = 0;
+ if (pSystemProperties)
+ pSystemProperties->GetMaxNetworkAdapters(chipsetType, &maxNetworkAdapters);
AssertMsg( ( !strcmp(pszDevice, "pcnet")
|| !strcmp(pszDevice, "e1000")
|| !strcmp(pszDevice, "virtio-net"))
&& uLun == 0
- && uInstance < SchemaDefs::NetworkAdapterCount,
+ && uInstance < maxNetworkAdapters,
("pszDevice=%s uLun=%d uInstance=%d\n", pszDevice, uLun, uInstance));
Log(("pszDevice=%s uLun=%d uInstance=%d\n", pszDevice, uLun, uInstance));
- AutoCaller autoCaller(pThis);
- AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
-
/*
* Suspend the VM first.
*
@@ -4677,8 +4792,6 @@ DECLCALLBACK(int) Console::changeNetworkAttachment(Console *pThis,
/**
* Called by IInternalSessionControl::OnSerialPortChange().
- *
- * @note Locks this object for writing.
*/
HRESULT Console::onSerialPortChange(ISerialPort *aSerialPort)
{
@@ -4687,96 +4800,111 @@ HRESULT Console::onSerialPortChange(ISerialPort *aSerialPort)
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ fireSerialPortChangedEvent(mEventSource, aSerialPort);
- HRESULT rc = S_OK;
+ LogFlowThisFunc(("Leaving rc=%#x\n", S_OK));
+ return S_OK;
+}
- /* don't trigger serial port change if the VM isn't running */
- SafeVMPtrQuiet ptrVM(this);
- if (ptrVM.isOk())
- {
- /* nothing to do so far */
- ptrVM.release();
- }
+/**
+ * Called by IInternalSessionControl::OnParallelPortChange().
+ */
+HRESULT Console::onParallelPortChange(IParallelPort *aParallelPort)
+{
+ LogFlowThisFunc(("\n"));
- /* notify console callbacks on success */
- if (SUCCEEDED(rc))
- fireSerialPortChangedEvent(mEventSource, aSerialPort);
+ AutoCaller autoCaller(this);
+ AssertComRCReturnRC(autoCaller.rc());
- LogFlowThisFunc(("Leaving rc=%#x\n", rc));
- return rc;
+ fireParallelPortChangedEvent(mEventSource, aParallelPort);
+
+ LogFlowThisFunc(("Leaving rc=%#x\n", S_OK));
+ return S_OK;
}
/**
- * Called by IInternalSessionControl::OnParallelPortChange().
- *
- * @note Locks this object for writing.
+ * Called by IInternalSessionControl::OnStorageControllerChange().
*/
-HRESULT Console::onParallelPortChange(IParallelPort *aParallelPort)
+HRESULT Console::onStorageControllerChange()
{
LogFlowThisFunc(("\n"));
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ fireStorageControllerChangedEvent(mEventSource);
+
+ LogFlowThisFunc(("Leaving rc=%#x\n", S_OK));
+ return S_OK;
+}
+
+/**
+ * Called by IInternalSessionControl::OnMediumChange().
+ */
+HRESULT Console::onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce)
+{
+ LogFlowThisFunc(("\n"));
+
+ AutoCaller autoCaller(this);
+ AssertComRCReturnRC(autoCaller.rc());
HRESULT rc = S_OK;
- /* don't trigger parallel port change if the VM isn't running */
+ /* don't trigger medium change if the VM isn't running */
SafeVMPtrQuiet ptrVM(this);
if (ptrVM.isOk())
{
- /* nothing to do so far */
+ rc = doMediumChange(aMediumAttachment, !!aForce, ptrVM);
ptrVM.release();
}
/* notify console callbacks on success */
if (SUCCEEDED(rc))
- fireParallelPortChangedEvent(mEventSource, aParallelPort);
+ fireMediumChangedEvent(mEventSource, aMediumAttachment);
LogFlowThisFunc(("Leaving rc=%#x\n", rc));
return rc;
}
/**
- * Called by IInternalSessionControl::OnStorageControllerChange().
+ * Called by IInternalSessionControl::OnCPUChange().
*
* @note Locks this object for writing.
*/
-HRESULT Console::onStorageControllerChange()
+HRESULT Console::onCPUChange(ULONG aCPU, BOOL aRemove)
{
LogFlowThisFunc(("\n"));
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
HRESULT rc = S_OK;
- /* don't trigger storage controller change if the VM isn't running */
+ /* don't trigger CPU change if the VM isn't running */
SafeVMPtrQuiet ptrVM(this);
if (ptrVM.isOk())
{
- /* nothing to do so far */
+ if (aRemove)
+ rc = doCPURemove(aCPU, ptrVM);
+ else
+ rc = doCPUAdd(aCPU, ptrVM);
ptrVM.release();
}
/* notify console callbacks on success */
if (SUCCEEDED(rc))
- fireStorageControllerChangedEvent(mEventSource);
+ fireCPUChangedEvent(mEventSource, aCPU, aRemove);
LogFlowThisFunc(("Leaving rc=%#x\n", rc));
return rc;
}
/**
- * Called by IInternalSessionControl::OnMediumChange().
+ * Called by IInternalSessionControl::OnCpuExecutionCapChange().
*
* @note Locks this object for writing.
*/
-HRESULT Console::onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce)
+HRESULT Console::onCPUExecutionCapChange(ULONG aExecutionCap)
{
LogFlowThisFunc(("\n"));
@@ -4787,61 +4915,80 @@ HRESULT Console::onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForc
HRESULT rc = S_OK;
- /* don't trigger medium change if the VM isn't running */
+ /* don't trigger the CPU priority change if the VM isn't running */
SafeVMPtrQuiet ptrVM(this);
if (ptrVM.isOk())
{
- rc = doMediumChange(aMediumAttachment, !!aForce, ptrVM);
+ if ( mMachineState == MachineState_Running
+ || mMachineState == MachineState_Teleporting
+ || mMachineState == MachineState_LiveSnapshotting
+ )
+ {
+ /* No need to call in the EMT thread. */
+ rc = VMR3SetCpuExecutionCap(ptrVM, aExecutionCap);
+ }
+ else
+ rc = setInvalidMachineStateError();
ptrVM.release();
}
/* notify console callbacks on success */
if (SUCCEEDED(rc))
- fireMediumChangedEvent(mEventSource, aMediumAttachment);
+ {
+ alock.release();
+ fireCPUExecutionCapChangedEvent(mEventSource, aExecutionCap);
+ }
LogFlowThisFunc(("Leaving rc=%#x\n", rc));
return rc;
}
/**
- * Called by IInternalSessionControl::OnCPUChange().
+ * Called by IInternalSessionControl::OnClipboardModeChange().
*
* @note Locks this object for writing.
*/
-HRESULT Console::onCPUChange(ULONG aCPU, BOOL aRemove)
+HRESULT Console::onClipboardModeChange(ClipboardMode_T aClipboardMode)
{
LogFlowThisFunc(("\n"));
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
HRESULT rc = S_OK;
- /* don't trigger CPU change if the VM isn't running */
+ /* don't trigger the Clipboard mode change if the VM isn't running */
SafeVMPtrQuiet ptrVM(this);
if (ptrVM.isOk())
{
- if (aRemove)
- rc = doCPURemove(aCPU, ptrVM);
+ if ( mMachineState == MachineState_Running
+ || mMachineState == MachineState_Teleporting
+ || mMachineState == MachineState_LiveSnapshotting)
+ changeClipboardMode(aClipboardMode);
else
- rc = doCPUAdd(aCPU, ptrVM);
+ rc = setInvalidMachineStateError();
ptrVM.release();
}
/* notify console callbacks on success */
if (SUCCEEDED(rc))
- fireCPUChangedEvent(mEventSource, aCPU, aRemove);
+ {
+ alock.release();
+ fireClipboardModeChangedEvent(mEventSource, aClipboardMode);
+ }
LogFlowThisFunc(("Leaving rc=%#x\n", rc));
return rc;
}
/**
- * Called by IInternalSessionControl::OnCpuExecutionCapChange().
+ * Called by IInternalSessionControl::OnDragAndDropModeChange().
*
* @note Locks this object for writing.
*/
-HRESULT Console::onCPUExecutionCapChange(ULONG aExecutionCap)
+HRESULT Console::onDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode)
{
LogFlowThisFunc(("\n"));
@@ -4852,18 +4999,14 @@ HRESULT Console::onCPUExecutionCapChange(ULONG aExecutionCap)
HRESULT rc = S_OK;
- /* don't trigger the CPU priority change if the VM isn't running */
+ /* don't trigger the Drag'n'drop mode change if the VM isn't running */
SafeVMPtrQuiet ptrVM(this);
if (ptrVM.isOk())
{
if ( mMachineState == MachineState_Running
|| mMachineState == MachineState_Teleporting
- || mMachineState == MachineState_LiveSnapshotting
- )
- {
- /* No need to call in the EMT thread. */
- rc = VMR3SetCpuExecutionCap(ptrVM, aExecutionCap);
- }
+ || mMachineState == MachineState_LiveSnapshotting)
+ changeDragAndDropMode(aDragAndDropMode);
else
rc = setInvalidMachineStateError();
ptrVM.release();
@@ -4871,7 +5014,10 @@ HRESULT Console::onCPUExecutionCapChange(ULONG aExecutionCap)
/* notify console callbacks on success */
if (SUCCEEDED(rc))
- fireCPUExecutionCapChangedEvent(mEventSource, aExecutionCap);
+ {
+ alock.release();
+ fireDragAndDropModeChangedEvent(mEventSource, aDragAndDropMode);
+ }
LogFlowThisFunc(("Leaving rc=%#x\n", rc));
return rc;
@@ -4906,7 +5052,7 @@ HRESULT Console::onVRDEServerChange(BOOL aRestart)
if (aRestart)
{
/* VRDP server may call this Console object back from other threads (VRDP INPUT or OUTPUT). */
- alock.leave();
+ alock.release();
if (vrdpEnabled)
{
@@ -4925,35 +5071,31 @@ HRESULT Console::onVRDEServerChange(BOOL aRestart)
mConsoleVRDPServer->Stop();
}
- alock.enter();
+ alock.acquire();
}
}
/* notify console callbacks on success */
if (SUCCEEDED(rc))
+ {
+ alock.release();
fireVRDEServerChangedEvent(mEventSource);
+ }
return rc;
}
-/**
- * @note Locks this object for reading.
- */
void Console::onVRDEServerInfoChange()
{
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
fireVRDEServerInfoChangedEvent(mEventSource);
}
/**
* Called by IInternalSessionControl::OnUSBControllerChange().
- *
- * @note Locks this object for writing.
*/
HRESULT Console::onUSBControllerChange()
{
@@ -4962,30 +5104,9 @@ HRESULT Console::onUSBControllerChange()
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ fireUSBControllerChangedEvent(mEventSource);
- HRESULT rc = S_OK;
-
- /* don't trigger USB controller change if the VM isn't running */
- SafeVMPtrQuiet ptrVM(this);
- if (ptrVM.isOk())
- {
- /// @todo implement one day.
- // Anyway, if we want to query the machine's USB Controller we need
- // to cache it to mUSBController in #init() (similar to mDVDDrive).
- //
- // bird: While the VM supports hot-plugging, I doubt any guest can
- // handle it at this time... :-)
-
- /* nothing to do so far */
- ptrVM.release();
- }
-
- /* notify console callbacks on success */
- if (SUCCEEDED(rc))
- fireUSBControllerChangedEvent(mEventSource);
-
- return rc;
+ return S_OK;
}
/**
@@ -5007,6 +5128,7 @@ HRESULT Console::onSharedFolderChange(BOOL aGlobal)
/* notify console callbacks on success */
if (SUCCEEDED(rc))
{
+ alock.release();
fireSharedFolderChangedEvent(mEventSource, aGlobal ? (Scope_T)Scope_Global : (Scope_T)Scope_Machine);
}
@@ -5053,6 +5175,7 @@ HRESULT Console::onUSBDeviceAttach(IUSBDevice *aDevice, IVirtualBoxErrorInfo *aE
if (aError != NULL)
{
/* notify callbacks about the error */
+ alock.release();
onUSBDeviceStateChange(aDevice, true /* aAttached */, aError);
return S_OK;
}
@@ -5064,6 +5187,7 @@ HRESULT Console::onUSBDeviceAttach(IUSBDevice *aDevice, IVirtualBoxErrorInfo *aE
return E_FAIL;
}
+ alock.release();
HRESULT rc = attachUSBDevice(aDevice, aMaskedIfs);
if (FAILED(rc))
{
@@ -5115,7 +5239,7 @@ HRESULT Console::onUSBDeviceDetach(IN_BSTR aId,
pUSBDevice = *it;
break;
}
- ++ it;
+ ++it;
}
@@ -5143,14 +5267,22 @@ HRESULT Console::onUSBDeviceDetach(IN_BSTR aId,
if (aError != NULL)
{
/* notify callback about an error */
+ alock.release();
onUSBDeviceStateChange(pUSBDevice, false /* aAttached */, aError);
return S_OK;
}
- HRESULT rc = detachUSBDevice(it);
+ /* Remove the device from the collection, it is re-added below for failures */
+ mUSBDevices.erase(it);
+ alock.release();
+ HRESULT rc = detachUSBDevice(pUSBDevice);
if (FAILED(rc))
{
+ /* Re-add the device to the collection */
+ alock.acquire();
+ mUSBDevices.push_back(pUSBDevice);
+ alock.release();
/* take the current error info */
com::ErrorInfoKeeper eik;
/* the error must be a VirtualBoxErrorInfo instance */
@@ -5196,17 +5328,28 @@ HRESULT Console::onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup)
)
{
/* No need to call in the EMT thread. */
- ULONG cMax;
+ LONG64 cMax;
Bstr strName;
+ BandwidthGroupType_T enmType;
rc = aBandwidthGroup->COMGETTER(Name)(strName.asOutParam());
if (SUCCEEDED(rc))
- rc = aBandwidthGroup->COMGETTER(MaxMbPerSec)(&cMax);
+ rc = aBandwidthGroup->COMGETTER(MaxBytesPerSec)(&cMax);
+ if (SUCCEEDED(rc))
+ rc = aBandwidthGroup->COMGETTER(Type)(&enmType);
if (SUCCEEDED(rc))
{
- int vrc;
- vrc = PDMR3AsyncCompletionBwMgrSetMaxForFile(ptrVM, Utf8Str(strName).c_str(),
- cMax * _1M);
+ int vrc = VINF_SUCCESS;
+ if (enmType == BandwidthGroupType_Disk)
+ vrc = PDMR3AsyncCompletionBwMgrSetMaxForFile(ptrVM, Utf8Str(strName).c_str(),
+ cMax);
+#ifdef VBOX_WITH_NETSHAPER
+ else if (enmType == BandwidthGroupType_Network)
+ vrc = PDMR3NsBwGroupSetLimit(ptrVM, Utf8Str(strName).c_str(),
+ cMax);
+ else
+ rc = E_NOTIMPL;
+#endif /* VBOX_WITH_NETSHAPER */
AssertRC(vrc);
}
}
@@ -5217,7 +5360,10 @@ HRESULT Console::onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup)
/* notify console callbacks on success */
if (SUCCEEDED(rc))
+ {
+ alock.release();
fireBandwidthGroupChangedEvent(mEventSource, aBandwidthGroup);
+ }
LogFlowThisFunc(("Leaving rc=%#x\n", rc));
return rc;
@@ -5235,8 +5381,6 @@ HRESULT Console::onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOO
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
HRESULT rc = S_OK;
/* don't trigger medium change if the VM isn't running */
@@ -5503,8 +5647,8 @@ HRESULT Console::onlineMergeMedium(IMediumAttachment *aMediumAttachment,
/** @todo AssertComRC -> AssertComRCReturn! Could potentially end up
* using uninitialized variables here. */
- BOOL fBuiltinIoCache;
- rc = mMachine->COMGETTER(IoCacheEnabled)(&fBuiltinIoCache);
+ BOOL fBuiltinIOCache;
+ rc = mMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache);
AssertComRC(rc);
SafeIfaceArray<IStorageController> ctrls;
rc = mMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls));
@@ -5588,7 +5732,7 @@ HRESULT Console::onlineMergeMedium(IMediumAttachment *aMediumAttachment,
uInstance,
enmBus,
fUseHostIOCache,
- fBuiltinIoCache,
+ fBuiltinIOCache,
true /* fSetupMerge */,
aSourceIdx,
aTargetIdx,
@@ -5664,7 +5808,7 @@ HRESULT Console::onlineMergeMedium(IMediumAttachment *aMediumAttachment,
uInstance,
enmBus,
fUseHostIOCache,
- fBuiltinIoCache,
+ fBuiltinIOCache,
false /* fSetupMerge */,
0 /* uMergeSource */,
0 /* uMergeTarget */,
@@ -5732,9 +5876,11 @@ HRESULT Console::updateMachineState(MachineState_T aMachineState)
return setMachineStateLocally(aMachineState);
}
+#ifdef CONSOLE_WITH_EVENT_CACHE
/**
* @note Locks this object for writing.
*/
+#endif
void Console::onMousePointerShapeChange(bool fVisible, bool fAlpha,
uint32_t xHot, uint32_t yHot,
uint32_t width, uint32_t height,
@@ -5749,27 +5895,31 @@ void Console::onMousePointerShapeChange(bool fVisible, bool fAlpha,
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- /* We need a write lock because we alter the cached callback data */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+#ifdef CONSOLE_WITH_EVENT_CACHE
+ {
+ /* We need a write lock because we alter the cached callback data */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Save the callback arguments */
- mCallbackData.mpsc.visible = fVisible;
- mCallbackData.mpsc.alpha = fAlpha;
- mCallbackData.mpsc.xHot = xHot;
- mCallbackData.mpsc.yHot = yHot;
- mCallbackData.mpsc.width = width;
- mCallbackData.mpsc.height = height;
-
- /* start with not valid */
- bool wasValid = mCallbackData.mpsc.valid;
- mCallbackData.mpsc.valid = false;
-
- com::SafeArray<BYTE> aShape(ComSafeArrayInArg(pShape));
- if (aShape.size() != 0)
- mCallbackData.mpsc.shape.initFrom(aShape);
- else
- mCallbackData.mpsc.shape.resize(0);
- mCallbackData.mpsc.valid = true;
+ /* Save the callback arguments */
+ mCallbackData.mpsc.visible = fVisible;
+ mCallbackData.mpsc.alpha = fAlpha;
+ mCallbackData.mpsc.xHot = xHot;
+ mCallbackData.mpsc.yHot = yHot;
+ mCallbackData.mpsc.width = width;
+ mCallbackData.mpsc.height = height;
+
+ /* start with not valid */
+ bool wasValid = mCallbackData.mpsc.valid;
+ mCallbackData.mpsc.valid = false;
+
+ com::SafeArray<BYTE> aShape(ComSafeArrayInArg(pShape));
+ if (aShape.size() != 0)
+ mCallbackData.mpsc.shape.initFrom(aShape);
+ else
+ mCallbackData.mpsc.shape.resize(0);
+ mCallbackData.mpsc.valid = true;
+ }
+#endif
fireMousePointerShapeChangedEvent(mEventSource, fVisible, fAlpha, xHot, yHot, width, height, ComSafeArrayInArg(pShape));
@@ -5778,9 +5928,11 @@ void Console::onMousePointerShapeChange(bool fVisible, bool fAlpha,
#endif
}
+#ifdef CONSOLE_WITH_EVENT_CACHE
/**
* @note Locks this object for writing.
*/
+#endif
void Console::onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelative, BOOL needsHostCursor)
{
LogFlowThisFunc(("supportsAbsolute=%d supportsRelative=%d needsHostCursor=%d\n",
@@ -5789,106 +5941,96 @@ void Console::onMouseCapabilityChange(BOOL supportsAbsolute, BOOL supportsRelati
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- /* We need a write lock because we alter the cached callback data */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+#ifdef CONSOLE_WITH_EVENT_CACHE
+ {
+ /* We need a write lock because we alter the cached callback data */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* save the callback arguments */
- mCallbackData.mcc.supportsAbsolute = supportsAbsolute;
- mCallbackData.mcc.supportsRelative = supportsRelative;
- mCallbackData.mcc.needsHostCursor = needsHostCursor;
- mCallbackData.mcc.valid = true;
+ /* save the callback arguments */
+ mCallbackData.mcc.supportsAbsolute = supportsAbsolute;
+ mCallbackData.mcc.supportsRelative = supportsRelative;
+ mCallbackData.mcc.needsHostCursor = needsHostCursor;
+ mCallbackData.mcc.valid = true;
+ }
+#endif
fireMouseCapabilityChangedEvent(mEventSource, supportsAbsolute, supportsRelative, needsHostCursor);
}
-/**
- * @note Locks this object for reading.
- */
void Console::onStateChange(MachineState_T machineState)
{
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
fireStateChangedEvent(mEventSource, machineState);
}
-/**
- * @note Locks this object for reading.
- */
void Console::onAdditionsStateChange()
{
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
fireAdditionsStateChangedEvent(mEventSource);
}
/**
- * @note Locks this object for reading.
- * This notification only is for reporting an incompatible
- * Guest Additions interface, *not* the Guest Additions version!
+ * @remarks This notification only is for reporting an incompatible
+ * Guest Additions interface, *not* the Guest Additions version!
*
- * The user will be notified inside the guest if new Guest
- * Additions are available (via VBoxTray/VBoxClient).
+ * The user will be notified inside the guest if new Guest
+ * Additions are available (via VBoxTray/VBoxClient).
*/
void Console::onAdditionsOutdated()
{
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ /** @todo implement this */
}
+#ifdef CONSOLE_WITH_EVENT_CACHE
/**
* @note Locks this object for writing.
*/
+#endif
void Console::onKeyboardLedsChange(bool fNumLock, bool fCapsLock, bool fScrollLock)
{
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- /* We need a write lock because we alter the cached callback data */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+#ifdef CONSOLE_WITH_EVENT_CACHE
+ {
+ /* We need a write lock because we alter the cached callback data */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* save the callback arguments */
- mCallbackData.klc.numLock = fNumLock;
- mCallbackData.klc.capsLock = fCapsLock;
- mCallbackData.klc.scrollLock = fScrollLock;
- mCallbackData.klc.valid = true;
+ /* save the callback arguments */
+ mCallbackData.klc.numLock = fNumLock;
+ mCallbackData.klc.capsLock = fCapsLock;
+ mCallbackData.klc.scrollLock = fScrollLock;
+ mCallbackData.klc.valid = true;
+ }
+#endif
fireKeyboardLedsChangedEvent(mEventSource, fNumLock, fCapsLock, fScrollLock);
}
-/**
- * @note Locks this object for reading.
- */
void Console::onUSBDeviceStateChange(IUSBDevice *aDevice, bool aAttached,
IVirtualBoxErrorInfo *aError)
{
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
fireUSBDeviceStateChangedEvent(mEventSource, aDevice, aAttached, aError);
}
-/**
- * @note Locks this object for reading.
- */
void Console::onRuntimeError(BOOL aFatal, IN_BSTR aErrorID, IN_BSTR aMessage)
{
AutoCaller autoCaller(this);
AssertComRCReturnVoid(autoCaller.rc());
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
fireRuntimeErrorEvent(mEventSource, aFatal, aErrorID, aMessage);
}
-/**
- * @note Locks this object for reading.
- */
HRESULT Console::onShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId)
{
AssertReturn(aCanShow, E_POINTER);
@@ -5900,9 +6042,7 @@ HRESULT Console::onShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId)
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
VBoxEventDesc evDesc;
-
if (aCheck)
{
evDesc.init(mEventSource, VBoxEventType_OnCanShowWindow);
@@ -5922,7 +6062,7 @@ HRESULT Console::onShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId)
}
else
{
- Assert(FALSE);
+ AssertFailed();
*aCanShow = TRUE;
}
}
@@ -5939,15 +6079,15 @@ HRESULT Console::onShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId)
ComPtr<IEvent> pEvent;
evDesc.getEvent(pEvent.asOutParam());
ComPtr<IShowWindowEvent> pShowEvent = pEvent;
- LONG64 aEvWinId = 0;
if (pShowEvent)
{
- pShowEvent->COMGETTER(WinId)(&aEvWinId);
- if ((aEvWinId != 0) && (*aWinId == 0))
- *aWinId = aEvWinId;
+ LONG64 iEvWinId = 0;
+ pShowEvent->COMGETTER(WinId)(&iEvWinId);
+ if (iEvWinId != 0 && *aWinId == 0)
+ *aWinId = iEvWinId;
}
else
- Assert(FALSE);
+ AssertFailed();
}
}
@@ -5984,7 +6124,10 @@ HRESULT Console::addVMCaller(bool aQuiet /* = false */,
bool aAllowNullVM /* = false */)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC(autoCaller.rc());
+ /** @todo Fix race during console/VM reference destruction, refer @bugref{6318}
+ * comment 25. */
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -6102,7 +6245,8 @@ HRESULT Console::consoleInitReleaseLog(const ComPtr<IMachine> aMachine)
Bstr logFolder;
hrc = aMachine->COMGETTER(LogFolder)(logFolder.asOutParam());
- if (FAILED(hrc)) return hrc;
+ if (FAILED(hrc))
+ return hrc;
Utf8Str logDir = logFolder;
@@ -6134,7 +6278,7 @@ HRESULT Console::consoleInitReleaseLog(const ComPtr<IMachine> aMachine)
Utf8Str *files[] = { &logFile, &pngFile };
Utf8Str oldName, newName;
- for (unsigned int j = 0; j < RT_ELEMENTS(files); ++ j)
+ for (unsigned int j = 0; j < RT_ELEMENTS(files); ++j)
{
if (i > 0)
oldName = Utf8StrFmt("%s.%d", files[j]->c_str(), i);
@@ -6151,88 +6295,17 @@ HRESULT Console::consoleInitReleaseLog(const ComPtr<IMachine> aMachine)
}
}
- static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
- char szError[RTPATH_MAX + 128] = "";
- PRTLOGGER pReleaseLogger;
- uint32_t fFlags = RTLOGFLAGS_PREFIX_TIME_PROG | RTLOGFLAGS_RESTRICT_GROUPS;
-#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
- fFlags |= RTLOGFLAGS_USECRLF;
-#endif
- int vrc = RTLogCreateEx(&pReleaseLogger, fFlags, "all all.restrict default.unrestricted",
- "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_FILE,
- NULL /* pfnBeginEnd */, 0 /* cHistory */, 0 /* cbHistoryFileMax */, 0 /* uHistoryTimeMax */,
- szError, sizeof(szError), logFile.c_str());
- if (RT_SUCCESS(vrc))
- {
- RTLogSetGroupLimit(pReleaseLogger, 32768);
-
- /* some introductory information */
- RTTIMESPEC timeSpec;
- char szTmp[256];
- RTTimeSpecToString(RTTimeNow(&timeSpec), szTmp, sizeof(szTmp));
- RTLogRelLogger(pReleaseLogger, 0, ~0U,
- "VirtualBox %s r%u %s (%s %s) release log\n"
-#ifdef VBOX_BLEEDING_EDGE
- "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n"
-#endif
- "Log opened %s\n",
- VBOX_VERSION_STRING, RTBldCfgRevision(), VBOX_BUILD_TARGET,
- __DATE__, __TIME__, szTmp);
-
- vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- RTLogRelLogger(pReleaseLogger, 0, ~0U, "OS Product: %s\n", szTmp);
- vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- RTLogRelLogger(pReleaseLogger, 0, ~0U, "OS Release: %s\n", szTmp);
- vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- RTLogRelLogger(pReleaseLogger, 0, ~0U, "OS Version: %s\n", szTmp);
- vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- RTLogRelLogger(pReleaseLogger, 0, ~0U, "OS Service Pack: %s\n", szTmp);
- vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- RTLogRelLogger(pReleaseLogger, 0, ~0U, "DMI Product Name: %s\n", szTmp);
- vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_VERSION, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- RTLogRelLogger(pReleaseLogger, 0, ~0U, "DMI Product Version: %s\n", szTmp);
-
- ComPtr<IHost> pHost;
- pVirtualBox->COMGETTER(Host)(pHost.asOutParam());
- ULONG cMbHostRam = 0;
- ULONG cMbHostRamAvail = 0;
- pHost->COMGETTER(MemorySize)(&cMbHostRam);
- pHost->COMGETTER(MemoryAvailable)(&cMbHostRamAvail);
- RTLogRelLogger(pReleaseLogger, 0, ~0U, "Host RAM: %uMB RAM, available: %uMB\n",
- cMbHostRam, cMbHostRamAvail);
-
- /* the package type is interesting for Linux distributions */
- char szExecName[RTPATH_MAX];
- char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
- RTLogRelLogger(pReleaseLogger, 0, ~0U,
- "Executable: %s\n"
- "Process ID: %u\n"
- "Package type: %s"
-#ifdef VBOX_OSE
- " (OSE)"
-#endif
- "\n",
- pszExecName ? pszExecName : "unknown",
- RTProcSelf(),
- VBOX_PACKAGE_STRING);
-
- /* register this logger as the release logger */
- RTLogRelSetDefaultInstance(pReleaseLogger);
- hrc = S_OK;
-
- /* Explicitly flush the log in case of VBOX_RELEASE_LOG=buffered. */
- RTLogFlush(pReleaseLogger);
- }
- else
- hrc = setError(E_FAIL,
- tr("Failed to open release log (%s, %Rrc)"),
- szError, vrc);
+ char szError[RTPATH_MAX + 128];
+ int vrc = com::VBoxLogRelCreate("VM", logFile.c_str(),
+ RTLOGFLAGS_PREFIX_TIME_PROG | RTLOGFLAGS_RESTRICT_GROUPS,
+ "all all.restrict default.unrestricted",
+ "VBOX_RELEASE_LOG", RTLOGDEST_FILE,
+ 32768 /* cMaxEntriesPerGroup */,
+ 0 /* cHistory */, 0 /* uHistoryFileTime */,
+ 0 /* uHistoryFileSize */, szError, sizeof(szError));
+ if (RT_FAILURE(vrc))
+ hrc = setError(E_FAIL, tr("Failed to open release log (%s, %Rrc)"),
+ szError, vrc);
/* If we've made any directory changes, flush the directory to increase
the likelihood that the log file will be usable after a system panic.
@@ -6276,6 +6349,12 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
tr("The virtual machine is already running or busy (machine state: %s)"),
Global::stringifyMachineState(mMachineState));
+ /* Set up release logging as early as possible after the check if
+ * there is already a running VM which we shouldn't disturb. */
+ rc = consoleInitReleaseLog(mMachine);
+ if (FAILED(rc))
+ throw rc;
+
/* test and clear the TeleporterEnabled property */
BOOL fTeleporterEnabled;
rc = mMachine->COMGETTER(TeleporterEnabled)(&fTeleporterEnabled);
@@ -6361,7 +6440,7 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
#if 0
/* the network cards will undergo a quick consistency check */
for (ULONG slot = 0;
- slot < SchemaDefs::NetworkAdapterCount;
+ slot < maxNetworkAdapters;
++slot)
{
ComPtr<INetworkAdapter> pNetworkAdapter;
@@ -6555,9 +6634,6 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
else
LogFlowThisFunc(("Machine has a current snapshot which is online, skipping immutable images reset\n"));
- rc = consoleInitReleaseLog(mMachine);
- if (FAILED(rc))
- throw rc;
#ifdef VBOX_WITH_EXTPACK
mptrExtPackManager->dumpAllToReleaseLog();
#endif
@@ -6638,7 +6714,7 @@ HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
int vrc = RTThreadCreate(NULL, Console::powerUpThread,
(void *)task.get(), 0,
- RTTHREADTYPE_MAIN_WORKER, 0, "VMPowerUp");
+ RTTHREADTYPE_MAIN_WORKER, 0, "VMPwrUp");
if (RT_FAILURE(vrc))
throw setError(E_FAIL, "Could not create VMPowerUp thread (%Rrc)", vrc);
@@ -6781,7 +6857,7 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
/* ----------------------------------------------------------------------
* DONE with necessary state changes, perform the power down actions (it's
- * safe to leave the object lock now if needed)
+ * safe to release the object lock now if needed)
* ---------------------------------------------------------------------- */
/* Stop the VRDP server to prevent new clients connection while VM is being
@@ -6792,16 +6868,16 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
/* Leave the lock since EMT will call us back as addVMCaller()
* in updateDisplayData(). */
- alock.leave();
+ alock.release();
mConsoleVRDPServer->Stop();
- alock.enter();
+ alock.acquire();
}
/* advance percent count */
if (aProgress)
- aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
+ aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount );
/* ----------------------------------------------------------------------
@@ -6822,16 +6898,16 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
LogFlowThisFunc(("Waiting for mpVM callers (%d) to drop to zero...\n",
mVMCallers));
- alock.leave();
+ alock.release();
RTSemEventWait(mVMZeroCallersSem, RT_INDEFINITE_WAIT);
- alock.enter();
+ alock.acquire();
}
/* advance percent count */
if (aProgress)
- aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
+ aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount );
vrc = VINF_SUCCESS;
@@ -6846,17 +6922,17 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
if (!mVMPoweredOff)
{
LogFlowThisFunc(("Powering off the VM...\n"));
- alock.leave();
+ alock.release();
vrc = VMR3PowerOff(VMR3GetVM(pUVM));
#ifdef VBOX_WITH_EXTPACK
mptrExtPackManager->callAllVmPowerOffHooks(this, VMR3GetVM(pUVM));
#endif
- alock.enter();
+ alock.acquire();
}
/* advance percent count */
if (aProgress)
- aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
+ aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount );
#ifdef VBOX_WITH_HGCM
/* Shutdown HGCM services before destroying the VM. */
@@ -6865,16 +6941,16 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
LogFlowThisFunc(("Shutdown HGCM...\n"));
/* Leave the lock since EMT will call us back as addVMCaller() */
- alock.leave();
+ alock.release();
m_pVMMDev->hgcmShutdown();
- alock.enter();
+ alock.acquire();
}
/* advance percent count */
if (aProgress)
- aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
+ aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);
#endif /* VBOX_WITH_HGCM */
@@ -6893,12 +6969,14 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
if (RT_SUCCESS(vrc))
{
fHasUSBController = true;
+ alock.release();
detachAllUSBDevices(false /* aDone */);
+ alock.acquire();
}
}
/* Now we've got to destroy the VM as well. (mpVM is not valid beyond
- * this point). We leave the lock before calling VMR3Destroy() because
+ * this point). We release the lock before calling VMR3Destroy() because
* it will result into calling destructors of drivers associated with
* Console children which may in turn try to lock Console (e.g. by
* instantiating SafeVMPtr to access mpVM). It's safe here because
@@ -6911,16 +6989,16 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
LogFlowThisFunc(("Destroying the VM...\n"));
- alock.leave();
+ alock.release();
vrc = VMR3Destroy(VMR3GetVM(pUVM));
/* take the lock again */
- alock.enter();
+ alock.acquire();
/* advance percent count */
if (aProgress)
- aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
+ aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);
if (RT_SUCCESS(vrc))
{
@@ -6946,11 +7024,15 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
/* Complete the detaching of the USB devices. */
if (fHasUSBController)
+ {
+ alock.release();
detachAllUSBDevices(true /* aDone */);
+ alock.acquire();
+ }
/* advance percent count */
if (aProgress)
- aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
+ aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);
}
else
{
@@ -6972,8 +7054,10 @@ HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
else
mVMDestroying = false;
+#ifdef CONSOLE_WITH_EVENT_CACHE
if (SUCCEEDED(rc))
mCallbackData.clear();
+#endif
LogFlowThisFuncLeave();
return rc;
@@ -7021,7 +7105,7 @@ HRESULT Console::setMachineState(MachineState_T aMachineState,
* Cross-lock conditions should be carefully watched out: calling
* UpdateState we will require Machine and SessionMachine locks
* (remember that here we're holding the Console lock here, and also
- * all locks that have been entered by the thread before calling
+ * all locks that have been acquire by the thread before calling
* this method).
*/
LogFlowThisFunc(("Doing mControl->UpdateState()...\n"));
@@ -7175,7 +7259,7 @@ HRESULT Console::fetchSharedFolders(BOOL aGlobal)
if (online)
{
for (SharedFolderDataMap::const_iterator it = oldFolders.begin();
- it != oldFolders.end(); ++ it)
+ it != oldFolders.end(); ++it)
{
if (m_mapSharedFolders.find(it->first) != m_mapSharedFolders.end())
; /* the console folder exists, nothing to do */
@@ -7275,14 +7359,15 @@ HRESULT Console::createSharedFolder(const Utf8Str &strName, const SharedFolderDa
aData.m_strHostPath.c_str(),
hostPathFull,
sizeof(hostPathFull));
+
+ bool fMissing = false;
if (RT_FAILURE(vrc))
return setError(E_INVALIDARG,
tr("Invalid shared folder path: '%s' (%Rrc)"),
aData.m_strHostPath.c_str(), vrc);
if (!RTPathExists(hostPathFull))
- return setError(E_INVALIDARG,
- tr("Shared folder path '%s' does not exist on the host"),
- aData.m_strHostPath.c_str());
+ fMissing = true;
+
/* Check whether the path is full (absolute) */
if (RTPathCompare(aData.m_strHostPath.c_str(), hostPathFull) != 0)
return setError(E_INVALIDARG,
@@ -7328,7 +7413,9 @@ HRESULT Console::createSharedFolder(const Utf8Str &strName, const SharedFolderDa
parms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
parms[2].u.uint32 = (aData.m_fWritable ? SHFL_ADD_MAPPING_F_WRITABLE : 0)
| (aData.m_fAutoMount ? SHFL_ADD_MAPPING_F_AUTOMOUNT : 0)
- | (fSymlinksCreate ? SHFL_ADD_MAPPING_F_CREATE_SYMLINKS : 0);
+ | (fSymlinksCreate ? SHFL_ADD_MAPPING_F_CREATE_SYMLINKS : 0)
+ | (fMissing ? SHFL_ADD_MAPPING_F_MISSING : 0)
+ ;
vrc = m_pVMMDev->hgcmHostCall("VBoxSharedFolders",
SHFL_FN_ADD_MAPPING,
@@ -7341,6 +7428,11 @@ HRESULT Console::createSharedFolder(const Utf8Str &strName, const SharedFolderDa
tr("Could not create a shared folder '%s' mapped to '%s' (%Rrc)"),
strName.c_str(), aData.m_strHostPath.c_str(), vrc);
+ if (fMissing)
+ return setError(E_INVALIDARG,
+ tr("Shared folder path '%s' does not exist on the host"),
+ aData.m_strHostPath.c_str());
+
return S_OK;
}
@@ -7494,7 +7586,7 @@ DECLCALLBACK(void) Console::vmstateChangeCallback(PVM aVM,
int vrc = RTThreadCreate(NULL, Console::powerDownThread,
(void *) task.get(), 0,
RTTHREADTYPE_MAIN_WORKER, 0,
- "VMPowerDown");
+ "VMPwrDwn");
AssertMsgRCBreak(vrc, ("Could not create VMPowerDown thread (%Rrc)\n", vrc));
/* task is now owned by powerDownThread(), so release it */
@@ -7721,6 +7813,80 @@ DECLCALLBACK(void) Console::vmstateChangeCallback(PVM aVM,
}
}
+/**
+ * Changes the clipboard mode.
+ *
+ * @param aClipboardMode new clipboard mode.
+ */
+void Console::changeClipboardMode(ClipboardMode_T aClipboardMode)
+{
+ VMMDev *pVMMDev = m_pVMMDev;
+ Assert(pVMMDev);
+
+ VBOXHGCMSVCPARM parm;
+ parm.type = VBOX_HGCM_SVC_PARM_32BIT;
+
+ switch (aClipboardMode)
+ {
+ default:
+ case ClipboardMode_Disabled:
+ LogRel(("Shared clipboard mode: Off\n"));
+ parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF;
+ break;
+ case ClipboardMode_GuestToHost:
+ LogRel(("Shared clipboard mode: Guest to Host\n"));
+ parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST;
+ break;
+ case ClipboardMode_HostToGuest:
+ LogRel(("Shared clipboard mode: Host to Guest\n"));
+ parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST;
+ break;
+ case ClipboardMode_Bidirectional:
+ LogRel(("Shared clipboard mode: Bidirectional\n"));
+ parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL;
+ break;
+ }
+
+ pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
+}
+
+/**
+ * Changes the drag'n_drop mode.
+ *
+ * @param aDragAndDropMode new drag'n'drop mode.
+ */
+void Console::changeDragAndDropMode(DragAndDropMode_T aDragAndDropMode)
+{
+ VMMDev *pVMMDev = m_pVMMDev;
+ Assert(pVMMDev);
+
+ VBOXHGCMSVCPARM parm;
+ parm.type = VBOX_HGCM_SVC_PARM_32BIT;
+
+ switch (aDragAndDropMode)
+ {
+ default:
+ case DragAndDropMode_Disabled:
+ LogRel(("Drag'n'drop mode: Off\n"));
+ parm.u.uint32 = VBOX_DRAG_AND_DROP_MODE_OFF;
+ break;
+ case ClipboardMode_GuestToHost:
+ LogRel(("Drag'n'drop mode: Guest to Host\n"));
+ parm.u.uint32 = VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST;
+ break;
+ case ClipboardMode_HostToGuest:
+ LogRel(("Drag'n'drop mode: Host to Guest\n"));
+ parm.u.uint32 = VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST;
+ break;
+ case ClipboardMode_Bidirectional:
+ LogRel(("Drag'n'drop mode: Bidirectional\n"));
+ parm.u.uint32 = VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL;
+ break;
+ }
+
+ pVMMDev->hgcmHostCall("VBoxDragAndDropSvc", DragAndDropSvc::HOST_DND_SET_MODE, 1, &parm);
+}
+
#ifdef VBOX_WITH_USB
/**
* Sends a request to VMM to attach the given host device.
@@ -7730,15 +7896,11 @@ DECLCALLBACK(void) Console::vmstateChangeCallback(PVM aVM,
* @param aHostDevice device to attach
*
* @note Synchronously calls EMT.
- * @note Must be called from under this object's lock.
*/
HRESULT Console::attachUSBDevice(IUSBDevice *aHostDevice, ULONG aMaskedIfs)
{
AssertReturn(aHostDevice, E_FAIL);
- AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
-
- /* still want a lock object because we need to leave it */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
HRESULT hrc;
@@ -7769,20 +7931,41 @@ HRESULT Console::attachUSBDevice(IUSBDevice *aHostDevice, ULONG aMaskedIfs)
LogFlowThisFunc(("Proxying USB device '%s' {%RTuuid}...\n",
Address.c_str(), uuid.raw()));
- /* leave the lock before a VMR3* call (EMT will call us back)! */
- alock.leave();
+ void *pvRemoteBackend = NULL;
+ if (fRemote)
+ {
+ RemoteUSBDevice *pRemoteUSBDevice = static_cast<RemoteUSBDevice *>(aHostDevice);
+ pvRemoteBackend = consoleVRDPServer()->USBBackendRequestPointer(pRemoteUSBDevice->clientId(), &uuid);
+ if (!pvRemoteBackend)
+ return E_INVALIDARG; /* The clientId is invalid then. */
+ }
+
+ USHORT portVersion = 1;
+ hrc = aHostDevice->COMGETTER(PortVersion)(&portVersion);
+ AssertComRCReturnRC(hrc);
+ Assert(portVersion == 1 || portVersion == 2);
-/** @todo just do everything here and only wrap the PDMR3Usb call. That'll offload some notification stuff from the EMT thread. */
- int vrc = VMR3ReqCallWait(ptrVM, VMCPUID_ANY,
- (PFNRT)usbAttachCallback, 7,
- this, ptrVM.raw(), aHostDevice, uuid.raw(), fRemote, Address.c_str(), aMaskedIfs);
+ int vrc = VMR3ReqCallWait(ptrVM, 0 /* idDstCpu (saved state, see #6232) */,
+ (PFNRT)usbAttachCallback, 9,
+ this, ptrVM.raw(), aHostDevice, uuid.raw(), fRemote, Address.c_str(), pvRemoteBackend, portVersion, aMaskedIfs);
- /* restore the lock */
- alock.enter();
+ if (RT_SUCCESS(vrc))
+ {
+ /* Create a OUSBDevice and add it to the device list */
+ ComObjPtr<OUSBDevice> pUSBDevice;
+ pUSBDevice.createObject();
+ hrc = pUSBDevice->init(aHostDevice);
+ AssertComRC(hrc);
- /* hrc is S_OK here */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ mUSBDevices.push_back(pUSBDevice);
+ LogFlowFunc(("Attached device {%RTuuid}\n", pUSBDevice->id().raw()));
- if (RT_FAILURE(vrc))
+ /* notify callbacks */
+ alock.release();
+ onUSBDeviceStateChange(pUSBDevice, true /* aAttached */, NULL);
+ }
+ else
{
LogWarningThisFunc(("Failed to create proxy device for '%s' {%RTuuid} (%Rrc)\n",
Address.c_str(), uuid.raw(), vrc));
@@ -7819,47 +8002,16 @@ HRESULT Console::attachUSBDevice(IUSBDevice *aHostDevice, ULONG aMaskedIfs)
*/
//static
DECLCALLBACK(int)
-Console::usbAttachCallback(Console *that, PVM pVM, IUSBDevice *aHostDevice, PCRTUUID aUuid, bool aRemote, const char *aAddress, ULONG aMaskedIfs)
+Console::usbAttachCallback(Console *that, PVM pVM, IUSBDevice *aHostDevice, PCRTUUID aUuid, bool aRemote, const char *aAddress, void *pvRemoteBackend, USHORT aPortVersion, ULONG aMaskedIfs)
{
LogFlowFuncEnter();
- LogFlowFunc(("that={%p}\n", that));
+ LogFlowFunc(("that={%p} aUuid={%RTuuid}\n", that, aUuid));
AssertReturn(that && aUuid, VERR_INVALID_PARAMETER);
-
- void *pvRemoteBackend = NULL;
- if (aRemote)
- {
- RemoteUSBDevice *pRemoteUSBDevice = static_cast<RemoteUSBDevice *>(aHostDevice);
- Guid guid(*aUuid);
-
- pvRemoteBackend = that->consoleVRDPServer()->USBBackendRequestPointer(pRemoteUSBDevice->clientId(), &guid);
- if (!pvRemoteBackend)
- return VERR_INVALID_PARAMETER; /* The clientId is invalid then. */
- }
-
- USHORT portVersion = 1;
- HRESULT hrc = aHostDevice->COMGETTER(PortVersion)(&portVersion);
- AssertComRCReturn(hrc, VERR_GENERAL_FAILURE);
- Assert(portVersion == 1 || portVersion == 2);
+ AssertReturn(!that->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
int vrc = PDMR3USBCreateProxyDevice(pVM, aUuid, aRemote, aAddress, pvRemoteBackend,
- portVersion == 1 ? VUSB_STDVER_11 : VUSB_STDVER_20, aMaskedIfs);
- if (RT_SUCCESS(vrc))
- {
- /* Create a OUSBDevice and add it to the device list */
- ComObjPtr<OUSBDevice> pUSBDevice;
- pUSBDevice.createObject();
- hrc = pUSBDevice->init(aHostDevice);
- AssertComRC(hrc);
-
- AutoWriteLock alock(that COMMA_LOCKVAL_SRC_POS);
- that->mUSBDevices.push_back(pUSBDevice);
- LogFlowFunc(("Attached device {%RTuuid}\n", pUSBDevice->id().raw()));
-
- /* notify callbacks */
- that->onUSBDeviceStateChange(pUSBDevice, true /* aAttached */, NULL);
- }
-
+ aPortVersion == 1 ? VUSB_STDVER_11 : VUSB_STDVER_20, aMaskedIfs);
LogFlowFunc(("vrc=%Rrc\n", vrc));
LogFlowFuncLeave();
return vrc;
@@ -7870,17 +8022,13 @@ Console::usbAttachCallback(Console *that, PVM pVM, IUSBDevice *aHostDevice, PCRT
* succeeds, the detached device will disappear from the mUSBDevices
* collection.
*
- * @param aIt Iterator pointing to the device to detach.
+ * @param aHostDevice device to attach
*
* @note Synchronously calls EMT.
- * @note Must be called from under this object's lock.
*/
-HRESULT Console::detachUSBDevice(USBDeviceList::iterator &aIt)
+HRESULT Console::detachUSBDevice(const ComObjPtr<OUSBDevice> &aHostDevice)
{
- AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
-
- /* still want a lock object because we need to leave it */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
/* Get the VM handle. */
SafeVMPtr ptrVM(this);
@@ -7890,16 +8038,39 @@ HRESULT Console::detachUSBDevice(USBDeviceList::iterator &aIt)
/* if the device is attached, then there must at least one USB hub. */
AssertReturn(PDMR3USBHasHub(ptrVM), E_FAIL);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("Detaching USB proxy device {%RTuuid}...\n",
- (*aIt)->id().raw()));
+ aHostDevice->id().raw()));
- /* leave the lock before a VMR3* call (EMT will call us back)! */
- alock.leave();
+ /*
+ * If this was a remote device, release the backend pointer.
+ * The pointer was requested in usbAttachCallback.
+ */
+ BOOL fRemote = FALSE;
+
+ HRESULT hrc2 = aHostDevice->COMGETTER(Remote)(&fRemote);
+ if (FAILED(hrc2))
+ setErrorStatic(hrc2, "GetRemote() failed");
+
+ PCRTUUID pUuid = aHostDevice->id().raw();
+ if (fRemote)
+ {
+ Guid guid(*pUuid);
+ consoleVRDPServer()->USBBackendReleasePointer(&guid);
+ }
-/** @todo just do everything here and only wrap the PDMR3Usb call. That'll offload some notification stuff from the EMT thread. */
- int vrc = VMR3ReqCallWait(ptrVM, VMCPUID_ANY,
+ alock.release();
+ int vrc = VMR3ReqCallWait(ptrVM, 0 /* idDstCpu (saved state, see #6232) */,
(PFNRT)usbDetachCallback, 5,
- this, ptrVM.raw(), &aIt, (*aIt)->id().raw());
+ this, ptrVM.raw(), pUuid);
+ if (RT_SUCCESS(vrc))
+ {
+ LogFlowFunc(("Detached device {%RTuuid}\n", pUuid));
+
+ /* notify callbacks */
+ onUSBDeviceStateChange(aHostDevice, false /* aAttached */, NULL);
+ }
+
ComAssertRCRet(vrc, E_FAIL);
return S_OK;
@@ -7912,48 +8083,19 @@ HRESULT Console::detachUSBDevice(USBDeviceList::iterator &aIt)
* interface pointers passed in.
*
* @thread EMT
- * @note Locks the console object for writing.
*/
//static
DECLCALLBACK(int)
-Console::usbDetachCallback(Console *that, PVM pVM, USBDeviceList::iterator *aIt, PCRTUUID aUuid)
+Console::usbDetachCallback(Console *that, PVM pVM, PCRTUUID aUuid)
{
LogFlowFuncEnter();
- LogFlowFunc(("that={%p}\n", that));
+ LogFlowFunc(("that={%p} aUuid={%RTuuid}\n", that, aUuid));
AssertReturn(that && aUuid, VERR_INVALID_PARAMETER);
- ComObjPtr<OUSBDevice> pUSBDevice = **aIt;
-
- /*
- * If that was a remote device, release the backend pointer.
- * The pointer was requested in usbAttachCallback.
- */
- BOOL fRemote = FALSE;
-
- HRESULT hrc2 = (**aIt)->COMGETTER(Remote)(&fRemote);
- if (FAILED(hrc2))
- setErrorStatic(hrc2, "GetRemote() failed");
-
- if (fRemote)
- {
- Guid guid(*aUuid);
- that->consoleVRDPServer()->USBBackendReleasePointer(&guid);
- }
+ AssertReturn(!that->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
int vrc = PDMR3USBDetachDevice(pVM, aUuid);
- if (RT_SUCCESS(vrc))
- {
- AutoWriteLock alock(that COMMA_LOCKVAL_SRC_POS);
-
- /* Remove the device from the collection */
- that->mUSBDevices.erase(*aIt);
- LogFlowFunc(("Detached device {%RTuuid}\n", pUSBDevice->id().raw()));
-
- /* notify callbacks */
- that->onUSBDeviceStateChange(pUSBDevice, false /* aAttached */, NULL);
- }
-
LogFlowFunc(("vrc=%Rrc\n", vrc));
LogFlowFuncLeave();
return vrc;
@@ -8213,8 +8355,19 @@ HRESULT Console::powerDownHostInterfaces()
/*
* host interface termination handling
*/
- HRESULT rc;
- for (ULONG slot = 0; slot < SchemaDefs::NetworkAdapterCount; slot ++)
+ HRESULT rc = S_OK;
+ ComPtr<IVirtualBox> pVirtualBox;
+ mMachine->COMGETTER(Parent)(pVirtualBox.asOutParam());
+ ComPtr<ISystemProperties> pSystemProperties;
+ if (pVirtualBox)
+ pVirtualBox->COMGETTER(SystemProperties)(pSystemProperties.asOutParam());
+ ChipsetType_T chipsetType = ChipsetType_PIIX3;
+ mMachine->COMGETTER(ChipsetType)(&chipsetType);
+ ULONG maxNetworkAdapters = 0;
+ if (pSystemProperties)
+ pSystemProperties->GetMaxNetworkAdapters(chipsetType, &maxNetworkAdapters);
+
+ for (ULONG slot = 0; slot < maxNetworkAdapters; slot++)
{
ComPtr<INetworkAdapter> pNetworkAdapter;
rc = mMachine->GetNetworkAdapter(slot, pNetworkAdapter.asOutParam());
@@ -8328,15 +8481,14 @@ Console::setVMRuntimeErrorCallback(PVM pVM, void *pvUser, uint32_t fFlags,
* Called at VM startup.
*
* @param pVM The VM handle.
- *
- * @note The caller must lock this object for writing.
*/
HRESULT Console::captureUSBDevices(PVM pVM)
{
LogFlowThisFunc(("\n"));
/* sanity check */
- ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
+ AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
/* If the machine has an USB controller, ask the USB proxy service to
* capture devices */
@@ -8344,11 +8496,10 @@ HRESULT Console::captureUSBDevices(PVM pVM)
int vrc = PDMR3QueryLun(pVM, "usb-ohci", 0, 0, &pBase);
if (RT_SUCCESS(vrc))
{
- /* leave the lock before calling Host in VBoxSVC since Host may call
+ /* release the lock before calling Host in VBoxSVC since Host may call
* us back from under its lock (e.g. onUSBDeviceAttach()) which would
* produce an inter-process dead-lock otherwise. */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- alock.leave();
+ alock.release();
HRESULT hrc = mControl->AutoCaptureUSBDevices();
ComAssertComRCRetRC(hrc);
@@ -8366,23 +8517,21 @@ HRESULT Console::captureUSBDevices(PVM pVM)
/**
* Detach all USB device which are attached to the VM for the
* purpose of clean up and such like.
- *
- * @note The caller must lock this object for writing.
*/
void Console::detachAllUSBDevices(bool aDone)
{
LogFlowThisFunc(("aDone=%RTbool\n", aDone));
/* sanity check */
- AssertReturnVoid(isWriteLockOnCurrentThread());
+ AssertReturnVoid(!isWriteLockOnCurrentThread());
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
mUSBDevices.clear();
- /* leave the lock before calling Host in VBoxSVC since Host may call
+ /* release the lock before calling Host in VBoxSVC since Host may call
* us back from under its lock (e.g. onUSBDeviceAttach()) which would
* produce an inter-process dead-lock otherwise. */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- alock.leave();
+ alock.release();
mControl->DetachAllUSBDevices(aDone);
}
@@ -8480,7 +8629,9 @@ void Console::processRemoteUSBDevices(uint32_t u32ClientId, VRDEUSBDEVICEDESC *p
if (fMatched)
{
+ alock.release();
hrc = onUSBDeviceAttach(pUSBDevice, NULL, fMaskedIfs);
+ alock.acquire();
/// @todo (r=dmik) warning reporting subsystem
@@ -8520,7 +8671,7 @@ void Console::processRemoteUSBDevices(uint32_t u32ClientId, VRDEUSBDEVICEDESC *p
break;
}
- ++ it;
+ ++it;
}
if (!pUSBDevice)
@@ -8545,7 +8696,9 @@ void Console::processRemoteUSBDevices(uint32_t u32ClientId, VRDEUSBDEVICEDESC *p
{
Bstr uuid;
pUSBDevice->COMGETTER(Id)(uuid.asOutParam());
+ alock.release();
onUSBDeviceDetach(uuid.raw(), NULL);
+ alock.acquire();
}
/* And remove it from the list. */
@@ -8596,7 +8749,7 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
* exact build was used to produce the core. */
static char saBuildID[40];
RTStrPrintf(saBuildID, sizeof(saBuildID), "%s%s%s%s VirtualBox %s r%u %s%s%s%s",
- "BU", "IL", "DI", "D", VBOX_VERSION_STRING, RTBldCfgRevision(), "BU", "IL", "DI", "D");
+ "BU", "IL", "DI", "D", RTBldCfgVersion(), RTBldCfgRevision(), "BU", "IL", "DI", "D");
ComObjPtr<Console> pConsole = task->mConsole;
@@ -8625,7 +8778,7 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
* the attached hard disks by calling LockMedia() below */
for (VMPowerUpTask::ProgressList::const_iterator
it = task->hardDiskProgresses.begin();
- it != task->hardDiskProgresses.end(); ++ it)
+ it != task->hardDiskProgresses.end(); ++it)
{
HRESULT rc2 = (*it)->WaitForCompletion(-1);
AssertComRC(rc2);
@@ -8653,11 +8806,11 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
Assert(server);
/* Does VRDP server call Console from the other thread?
- * Not sure (and can change), so leave the lock just in case.
+ * Not sure (and can change), so release the lock just in case.
*/
- alock.leave();
+ alock.release();
vrc = server->Launch();
- alock.enter();
+ alock.acquire();
if (vrc == VERR_NET_ADDRESS_IN_USE)
{
@@ -8705,10 +8858,10 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
*/
PVM pVM;
/*
- * leave the lock since EMT will call Console. It's safe because
+ * release the lock since EMT will call Console. It's safe because
* mMachineState is either Starting or Restoring state here.
*/
- alock.leave();
+ alock.release();
vrc = VMR3Create(cCpus,
pConsole->mpVmm2UserMethods,
@@ -8718,7 +8871,7 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
static_cast<Console *>(pConsole),
&pVM);
- alock.enter();
+ alock.acquire();
/* Enable client connections to the server. */
pConsole->consoleVRDPServer()->EnableConnections();
@@ -8755,8 +8908,8 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
if (pConsole->m_pVMMDev->isShFlActive())
{
/* Does the code below call Console from the other thread?
- * Not sure, so leave the lock just in case. */
- alock.leave();
+ * Not sure, so release the lock just in case. */
+ alock.release();
for (SharedFolderDataMap::const_iterator it = task->mSharedFolders.begin();
it != task->mSharedFolders.end();
@@ -8776,19 +8929,19 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
if (FAILED(rc))
rc = S_OK; // do not fail with broken shared folders
- /* enter the lock again */
- alock.enter();
+ /* acquire the lock again */
+ alock.acquire();
}
+ /* release the lock before a lengthy operation */
+ alock.release();
+
/*
* Capture USB devices.
*/
rc = pConsole->captureUSBDevices(pVM);
if (FAILED(rc)) break;
- /* leave the lock before a lengthy operation */
- alock.leave();
-
/* Load saved state? */
if (task->mSavedStateFile.length())
{
@@ -8900,8 +9053,8 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
AssertLogRelRC(vrc);
}
- /* enter the lock again */
- alock.enter();
+ /* acquire the lock again */
+ alock.acquire();
}
while (0);
@@ -8913,7 +9066,9 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
/* powerDown() will call VMR3Destroy() and do all necessary
* cleanup (VRDP, USB devices) */
+ alock.release();
HRESULT rc2 = pConsole->powerDown();
+ alock.acquire();
AssertComRC(rc2);
}
else
@@ -8923,10 +9078,10 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
* pfnVMAtError() function passed to VMR3Create() is supposed to
* be sticky but our error callback isn't.
*/
- alock.leave();
+ alock.release();
VMR3AtErrorDeregister(pVM, Console::genericVMSetErrorCallback, &task->mErrorMsg);
/** @todo register another VMSetError callback? */
- alock.enter();
+ alock.acquire();
}
}
else
@@ -8992,8 +9147,8 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
* is already set by vmstateChangeCallback() in all cases.
*/
- /* leave the lock, don't need it any more */
- alock.leave();
+ /* release the lock, don't need it any more */
+ alock.release();
if (SUCCEEDED(rc))
{
@@ -9044,7 +9199,7 @@ DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pConsole,
unsigned uInstance,
StorageBus_T enmBus,
bool fUseHostIOCache,
- bool fBuiltinIoCache,
+ bool fBuiltinIOCache,
bool fSetupMerge,
unsigned uMergeSource,
unsigned uMergeTarget,
@@ -9079,7 +9234,7 @@ DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pConsole,
uInstance,
enmBus,
fUseHostIOCache,
- fBuiltinIoCache,
+ fBuiltinIOCache,
fSetupMerge,
uMergeSource,
uMergeTarget,
@@ -9164,13 +9319,13 @@ DECLCALLBACK(int) Console::fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)
fBeganTakingSnapshot = true;
- /*
- * state file is non-null only when the VM is paused
- * (i.e. creating a snapshot online)
- */
- bool f = (!pTask->bstrSavedStateFile.isEmpty() && pTask->fTakingSnapshotOnline)
- || ( pTask->bstrSavedStateFile.isEmpty() && !pTask->fTakingSnapshotOnline);
- if (!f)
+ /* Check sanity: for offline snapshots there must not be a saved state
+ * file name. All other combinations are valid (even though online
+ * snapshots without saved state file seems inconsistent - there are
+ * some exotic use cases, which need to be explicitly enabled, see the
+ * code of SessionMachine::BeginTakingSnapshot. */
+ if ( !pTask->fTakingSnapshotOnline
+ && !pTask->bstrSavedStateFile.isEmpty())
throw setErrorStatic(E_FAIL, "Invalid state of saved state file");
/* sync the state with the server */
@@ -9182,31 +9337,38 @@ DECLCALLBACK(int) Console::fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)
// STEP 3: save the VM state (if online)
if (pTask->fTakingSnapshotOnline)
{
- Utf8Str strSavedStateFile(pTask->bstrSavedStateFile);
-
+ int vrc;
SafeVMPtr ptrVM(that);
if (!ptrVM.isOk())
throw ptrVM.rc();
pTask->mProgress->SetNextOperation(Bstr(tr("Saving the machine state")).raw(),
pTask->ulMemSize); // operation weight, same as computed when setting up progress object
- pTask->mProgress->setCancelCallback(takesnapshotProgressCancelCallback, ptrVM.rawUVM());
+ if (!pTask->bstrSavedStateFile.isEmpty())
+ {
+ Utf8Str strSavedStateFile(pTask->bstrSavedStateFile);
+
+ pTask->mProgress->setCancelCallback(takesnapshotProgressCancelCallback, ptrVM.rawUVM());
- alock.leave();
- LogFlowFunc(("VMR3Save...\n"));
- int vrc = VMR3Save(ptrVM,
+ alock.release();
+ LogFlowFunc(("VMR3Save...\n"));
+ vrc = VMR3Save(ptrVM,
strSavedStateFile.c_str(),
true /*fContinueAfterwards*/,
Console::stateProgressCallback,
static_cast<IProgress *>(pTask->mProgress),
&fSuspenededBySave);
- alock.enter();
- if (RT_FAILURE(vrc))
- throw setErrorStatic(E_FAIL,
- tr("Failed to save the machine state to '%s' (%Rrc)"),
- strSavedStateFile.c_str(), vrc);
+ alock.acquire();
+ if (RT_FAILURE(vrc))
+ throw setErrorStatic(E_FAIL,
+ tr("Failed to save the machine state to '%s' (%Rrc)"),
+ strSavedStateFile.c_str(), vrc);
+
+ pTask->mProgress->setCancelCallback(NULL, NULL);
+ }
+ else
+ LogRel(("Console: skipped saving state as part of online snapshot\n"));
- pTask->mProgress->setCancelCallback(NULL, NULL);
if (!pTask->mProgress->notifyPointOfNoReturn())
throw setErrorStatic(E_FAIL, tr("Canceled"));
that->mptrCancelableProgress.setNull();
@@ -9262,13 +9424,13 @@ DECLCALLBACK(int) Console::fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)
const char *pcszDevice = Console::convertControllerTypeToDev(enmController);
- BOOL fBuiltinIoCache;
- rc = that->mMachine->COMGETTER(IoCacheEnabled)(&fBuiltinIoCache);
+ BOOL fBuiltinIOCache;
+ rc = that->mMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache);
if (FAILED(rc))
throw rc;
/*
- * don't leave the lock since reconfigureMediumAttachment
+ * don't release the lock since reconfigureMediumAttachment
* isn't going to need the Console lock.
*/
vrc = VMR3ReqCallWait(ptrVM,
@@ -9281,7 +9443,7 @@ DECLCALLBACK(int) Console::fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)
lInstance,
enmBus,
fUseHostIOCache,
- fBuiltinIoCache,
+ fBuiltinIOCache,
false /* fSetupMerge */,
0 /* uMergeSource */,
0 /* uMergeTarget */,
@@ -9343,9 +9505,9 @@ DECLCALLBACK(int) Console::fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)
{
LogFlowFunc(("VMR3Resume...\n"));
SafeVMPtr ptrVM(that);
- alock.leave();
+ alock.release();
int vrc = VMR3Resume(ptrVM);
- alock.enter();
+ alock.acquire();
if (RT_FAILURE(vrc))
{
rc = setErrorStatic(VBOX_E_VM_ERROR, tr("Could not resume the machine execution (%Rrc)"), vrc);
@@ -9401,9 +9563,9 @@ DECLCALLBACK(int) Console::fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)
Assert(pTask->lastMachineState == MachineState_Running);
LogFlowFunc(("VMR3Resume (on failure)...\n"));
SafeVMPtr ptrVM(that);
- alock.leave();
+ alock.release();
int vrc = VMR3Resume(ptrVM); AssertLogRelRC(vrc);
- alock.enter();
+ alock.acquire();
if (RT_FAILURE(vrc))
that->setMachineState(MachineState_Paused);
}
@@ -9489,7 +9651,9 @@ DECLCALLBACK(int) Console::saveStateThread(RTTHREAD Thread, void *pvUser)
* deadlock.
*/
task->releaseVMCaller();
+ thatLock.release();
rc = that->powerDown();
+ thatLock.acquire();
}
/*
@@ -9543,6 +9707,8 @@ DECLCALLBACK(int) Console::powerDownThread(RTTHREAD Thread, void *pvUser)
/* release VM caller to avoid the powerDown() deadlock */
task->releaseVMCaller();
+ thatLock.release();
+
that->powerDown(task->mServerProgress);
/* complete the operation */
diff --git a/src/VBox/Main/src-client/ConsoleImpl2.cpp b/src/VBox/Main/src-client/ConsoleImpl2.cpp
index a038d1755..3b62f1628 100644
--- a/src/VBox/Main/src-client/ConsoleImpl2.cpp
+++ b/src/VBox/Main/src-client/ConsoleImpl2.cpp
@@ -1,6 +1,6 @@
/* $Id: ConsoleImpl2.cpp $ */
/** @file
- * VBox Console COM Class implementation
+ * VBox Console COM Class implementation - VM Configuration Bits.
*
* @remark We've split out the code that the 64-bit VC++ v8 compiler finds
* problematic to optimize so we can disable optimizations and later,
@@ -9,7 +9,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -31,10 +31,13 @@
#ifdef VBOX_WITH_GUEST_CONTROL
# include "GuestImpl.h"
#endif
+#ifdef VBOX_WITH_DRAG_AND_DROP
+# include "GuestDnDImpl.h"
+#endif
#include "VMMDev.h"
#include "Global.h"
#ifdef VBOX_WITH_PCI_PASSTHROUGH
-# include "PciRawDevImpl.h"
+# include "PCIRawDevImpl.h"
#endif
// generated header
@@ -213,7 +216,7 @@ const char* controllerString(StorageControllerType_T enmType)
struct BootNic
{
ULONG mInstance;
- PciBusAddress mPciAddress;
+ PCIBusAddress mPCIAddress;
ULONG mBootPrio;
bool operator < (const BootNic &rhs) const
@@ -462,17 +465,17 @@ static void RemoveConfigValue(PCFGMNODE pNode,
}
#ifdef VBOX_WITH_PCI_PASSTHROUGH
-HRESULT Console::attachRawPciDevices(PVM pVM,
+HRESULT Console::attachRawPCIDevices(PVM pVM,
BusAssignmentManager *BusMgr,
PCFGMNODE pDevices)
{
HRESULT hrc = S_OK;
PCFGMNODE pInst, pCfg, pLunL0, pLunL1;
- SafeIfaceArray<IPciDeviceAttachment> assignments;
+ SafeIfaceArray<IPCIDeviceAttachment> assignments;
ComPtr<IMachine> aMachine = machine();
- hrc = aMachine->COMGETTER(PciDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
+ hrc = aMachine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
if ( hrc != S_OK
|| assignments.size() < 1)
return hrc;
@@ -486,15 +489,15 @@ HRESULT Console::attachRawPciDevices(PVM pVM,
* distribution model.
*/
# ifdef VBOX_WITH_EXTPACK
- static const char *s_pszPciRawExtPackName = "Oracle VM VirtualBox Extension Pack";
- if (!mptrExtPackManager->isExtPackUsable(s_pszPciRawExtPackName))
+ static const char *s_pszPCIRawExtPackName = "Oracle VM VirtualBox Extension Pack";
+ if (!mptrExtPackManager->isExtPackUsable(s_pszPCIRawExtPackName))
{
/* Always fatal! */
return VMSetError(pVM, VERR_NOT_FOUND, RT_SRC_POS,
N_("Implementation of the PCI passthrough framework not found!\n"
"The VM cannot be started. To fix this problem, either "
"install the '%s' or disable PCI passthrough via VBoxManage"),
- s_pszPciRawExtPackName);
+ s_pszPCIRawExtPackName);
}
# endif
@@ -504,20 +507,20 @@ HRESULT Console::attachRawPciDevices(PVM pVM,
/* Find required bridges, and add missing ones */
for (size_t iDev = 0; iDev < assignments.size(); iDev++)
{
- ComPtr<IPciDeviceAttachment> assignment = assignments[iDev];
+ ComPtr<IPCIDeviceAttachment> assignment = assignments[iDev];
LONG guest = 0;
- PciBusAddress GuestPciAddress;
+ PCIBusAddress GuestPCIAddress;
assignment->COMGETTER(GuestAddress)(&guest);
- GuestPciAddress.fromLong(guest);
- Assert(GuestPciAddress.valid());
+ GuestPCIAddress.fromLong(guest);
+ Assert(GuestPCIAddress.valid());
- if (GuestPciAddress.miBus > 0)
+ if (GuestPCIAddress.miBus > 0)
{
int iBridgesMissed = 0;
- int iBase = GuestPciAddress.miBus - 1;
+ int iBase = GuestPCIAddress.miBus - 1;
- while (!BusMgr->hasPciDevice("ich9pcibridge", iBase) && iBase > 0)
+ while (!BusMgr->hasPCIDevice("ich9pcibridge", iBase) && iBase > 0)
{
iBridgesMissed++; iBase--;
}
@@ -527,21 +530,21 @@ HRESULT Console::attachRawPciDevices(PVM pVM,
{
InsertConfigNode(pBridges, Utf8StrFmt("%d", iBase + iBridge).c_str(), &pInst);
InsertConfigInteger(pInst, "Trusted", 1);
- hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst);
+ hrc = BusMgr->assignPCIDevice("ich9pcibridge", pInst);
}
}
}
/* Now actually add devices */
- PCFGMNODE pPciDevs = NULL;
+ PCFGMNODE pPCIDevs = NULL;
if (assignments.size() > 0)
{
- InsertConfigNode(pDevices, "pciraw", &pPciDevs);
+ InsertConfigNode(pDevices, "pciraw", &pPCIDevs);
PCFGMNODE pRoot = CFGMR3GetParent(pDevices); Assert(pRoot);
- /* Tell PGM to tell GPciRaw about guest mappings. */
+ /* Tell PGM to tell GPCIRaw about guest mappings. */
CFGMR3InsertNode(pRoot, "PGM", NULL);
InsertConfigInteger(CFGMR3GetChild(pRoot, "PGM"), "PciPassThrough", 1);
@@ -556,8 +559,8 @@ HRESULT Console::attachRawPciDevices(PVM pVM,
for (size_t iDev = 0; iDev < assignments.size(); iDev++)
{
- PciBusAddress HostPciAddress, GuestPciAddress;
- ComPtr<IPciDeviceAttachment> assignment = assignments[iDev];
+ PCIBusAddress HostPCIAddress, GuestPCIAddress;
+ ComPtr<IPCIDeviceAttachment> assignment = assignments[iDev];
LONG host, guest;
Bstr aDevName;
@@ -565,28 +568,28 @@ HRESULT Console::attachRawPciDevices(PVM pVM,
assignment->COMGETTER(GuestAddress)(&guest);
assignment->COMGETTER(Name)(aDevName.asOutParam());
- InsertConfigNode(pPciDevs, Utf8StrFmt("%d", iDev).c_str(), &pInst);
+ InsertConfigNode(pPCIDevs, Utf8StrFmt("%d", iDev).c_str(), &pInst);
InsertConfigInteger(pInst, "Trusted", 1);
- HostPciAddress.fromLong(host);
- Assert(HostPciAddress.valid());
+ HostPCIAddress.fromLong(host);
+ Assert(HostPCIAddress.valid());
InsertConfigNode(pInst, "Config", &pCfg);
InsertConfigString(pCfg, "DeviceName", aDevName);
InsertConfigInteger(pCfg, "DetachHostDriver", 1);
- InsertConfigInteger(pCfg, "HostPCIBusNo", HostPciAddress.miBus);
- InsertConfigInteger(pCfg, "HostPCIDeviceNo", HostPciAddress.miDevice);
- InsertConfigInteger(pCfg, "HostPCIFunctionNo", HostPciAddress.miFn);
+ InsertConfigInteger(pCfg, "HostPCIBusNo", HostPCIAddress.miBus);
+ InsertConfigInteger(pCfg, "HostPCIDeviceNo", HostPCIAddress.miDevice);
+ InsertConfigInteger(pCfg, "HostPCIFunctionNo", HostPCIAddress.miFn);
- GuestPciAddress.fromLong(guest);
- Assert(GuestPciAddress.valid());
- hrc = BusMgr->assignHostPciDevice("pciraw", pInst, HostPciAddress, GuestPciAddress, true);
+ GuestPCIAddress.fromLong(guest);
+ Assert(GuestPCIAddress.valid());
+ hrc = BusMgr->assignHostPCIDevice("pciraw", pInst, HostPCIAddress, GuestPCIAddress, true);
if (hrc != S_OK)
return hrc;
- InsertConfigInteger(pCfg, "GuestPCIBusNo", GuestPciAddress.miBus);
- InsertConfigInteger(pCfg, "GuestPCIDeviceNo", GuestPciAddress.miDevice);
- InsertConfigInteger(pCfg, "GuestPCIFunctionNo", GuestPciAddress.miFn);
+ InsertConfigInteger(pCfg, "GuestPCIBusNo", GuestPCIAddress.miBus);
+ InsertConfigInteger(pCfg, "GuestPCIDeviceNo", GuestPCIAddress.miDevice);
+ InsertConfigInteger(pCfg, "GuestPCIFunctionNo", GuestPCIAddress.miFn);
/* the driver */
InsertConfigNode(pInst, "LUN#0", &pLunL0);
@@ -596,7 +599,7 @@ HRESULT Console::attachRawPciDevices(PVM pVM,
/* the Main driver */
InsertConfigString(pLunL1, "Driver", "MainPciRaw");
InsertConfigNode(pLunL1, "Config", &pCfg);
- PciRawDev* pMainDev = new PciRawDev(this);
+ PCIRawDev* pMainDev = new PCIRawDev(this);
InsertConfigInteger(pCfg, "Object", (uintptr_t)pMainDev);
}
@@ -660,7 +663,15 @@ DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole)
*/
PUVM pUVM = pConsole->mpUVM = VMR3GetUVM(pVM);
VMR3RetainUVM(pUVM);
- int vrc = pConsole->configConstructorInner(pVM, &alock);
+ int vrc;
+ try
+ {
+ vrc = pConsole->configConstructorInner(pVM, &alock);
+ }
+ catch (...)
+ {
+ vrc = VERR_UNEXPECTED_EXCEPTION;
+ }
if (RT_FAILURE(vrc))
{
pConsole->mpUVM = NULL;
@@ -745,6 +756,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
Bstr osTypeId;
hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H();
+ LogRel(("OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
BOOL fIOAPIC;
hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H();
@@ -756,6 +768,8 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
hrc = guestOSType->COMGETTER(FamilyId)(guestTypeFamilyId.asOutParam()); H();
BOOL fOsXGuest = guestTypeFamilyId == Bstr("MacOS");
+ ULONG maxNetworkAdapters;
+ hrc = systemProperties->GetMaxNetworkAdapters(chipsetType, &maxNetworkAdapters); H();
/*
* Get root node first.
* This is the only node in the tree.
@@ -914,9 +928,9 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
if ( !fIsGuest64Bit
&& fIOAPIC
&& ( osTypeId == "WindowsNT4"
- || osTypeId == "Windows2000"
- || osTypeId == "WindowsXP"
- || osTypeId == "Windows2003"))
+ || osTypeId == "Windows2000"
+ || osTypeId == "WindowsXP"
+ || osTypeId == "Windows2003"))
{
/* Only allow TPR patching for NT, Win2k, XP and Windows Server 2003. (32 bits mode)
* We may want to consider adding more guest OSes (Solaris) later on.
@@ -955,6 +969,9 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
hrc = pMachine->GetCPUProperty(CPUPropertyType_Synthetic, &fSyntheticCpu); H();
InsertConfigInteger(pCPUM, "SyntheticCpu", fSyntheticCpu);
+ if (fOsXGuest)
+ InsertConfigInteger(pCPUM, "EnableHVP", 1);
+
BOOL fPXEDebug;
hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H();
@@ -988,7 +1005,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
/* I/O cache size */
ULONG ioCacheSize = 5;
- hrc = pMachine->COMGETTER(IoCacheSize)(&ioCacheSize); H();
+ hrc = pMachine->COMGETTER(IOCacheSize)(&ioCacheSize); H();
InsertConfigInteger(pPDMBlkCache, "CacheSize", ioCacheSize * _1M);
/*
@@ -1007,25 +1024,41 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pPDM, "AsyncCompletion", &pAc);
InsertConfigNode(pAc, "File", &pAcFile);
InsertConfigNode(pAcFile, "BwGroups", &pAcFileBwGroups);
+#ifdef VBOX_WITH_NETSHAPER
+ PCFGMNODE pNetworkShaper;
+ PCFGMNODE pNetworkBwGroups;
+
+ InsertConfigNode(pPDM, "NetworkShaper", &pNetworkShaper);
+ InsertConfigNode(pNetworkShaper, "BwGroups", &pNetworkBwGroups);
+#endif /* VBOX_WITH_NETSHAPER */
for (size_t i = 0; i < bwGroups.size(); i++)
{
Bstr strName;
- ULONG cMaxMbPerSec;
+ LONG64 cMaxBytesPerSec;
BandwidthGroupType_T enmType;
hrc = bwGroups[i]->COMGETTER(Name)(strName.asOutParam()); H();
hrc = bwGroups[i]->COMGETTER(Type)(&enmType); H();
- hrc = bwGroups[i]->COMGETTER(MaxMbPerSec)(&cMaxMbPerSec); H();
+ hrc = bwGroups[i]->COMGETTER(MaxBytesPerSec)(&cMaxBytesPerSec); H();
if (enmType == BandwidthGroupType_Disk)
{
PCFGMNODE pBwGroup;
InsertConfigNode(pAcFileBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
- InsertConfigInteger(pBwGroup, "Max", cMaxMbPerSec * _1M);
- InsertConfigInteger(pBwGroup, "Start", cMaxMbPerSec * _1M);
+ InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
+ InsertConfigInteger(pBwGroup, "Start", cMaxBytesPerSec);
InsertConfigInteger(pBwGroup, "Step", 0);
}
+#ifdef VBOX_WITH_NETSHAPER
+ else if (enmType == BandwidthGroupType_Network)
+ {
+ /* Network bandwidth groups. */
+ PCFGMNODE pBwGroup;
+ InsertConfigNode(pNetworkBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
+ InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
+ }
+#endif /* VBOX_WITH_NETSHAPER */
}
/*
@@ -1070,20 +1103,20 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
/*
* PCI buses.
*/
- uint32_t uIocPciAddress, uHbcPciAddress;
+ uint32_t uIocPCIAddress, uHbcPCIAddress;
switch (chipsetType)
{
default:
Assert(false);
case ChipsetType_PIIX3:
InsertConfigNode(pDevices, "pci", &pDev);
- uHbcPciAddress = (0x0 << 16) | 0;
- uIocPciAddress = (0x1 << 16) | 0; // ISA controller
+ uHbcPCIAddress = (0x0 << 16) | 0;
+ uIocPCIAddress = (0x1 << 16) | 0; // ISA controller
break;
case ChipsetType_ICH9:
InsertConfigNode(pDevices, "ich9pci", &pDev);
- uHbcPciAddress = (0x1e << 16) | 0;
- uIocPciAddress = (0x1f << 16) | 0; // LPC controller
+ uHbcPCIAddress = (0x1e << 16) | 0;
+ uIocPCIAddress = (0x1f << 16) | 0; // LPC controller
break;
}
InsertConfigNode(pDev, "0", &pInst);
@@ -1101,31 +1134,33 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDevices, "ich9pcibridge", &pDev);
InsertConfigNode(pDev, "0", &pInst);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst); H();
+ hrc = BusMgr->assignPCIDevice("ich9pcibridge", pInst); H();
InsertConfigNode(pDev, "1", &pInst);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst); H();
+ hrc = BusMgr->assignPCIDevice("ich9pcibridge", pInst); H();
#ifdef VBOX_WITH_PCI_PASSTHROUGH
/* Add PCI passthrough devices */
- hrc = attachRawPciDevices(pVM, BusMgr, pDevices); H();
+ hrc = attachRawPCIDevices(pVM, BusMgr, pDevices); H();
#endif
}
+
/*
- * Enable 3 following devices: HPET, SMC, LPC on MacOS X guests or on ICH9 chipset
+ * Enable the following devices: HPET, SMC and LPC on MacOS X guests or on ICH9 chipset
*/
+
/*
* High Precision Event Timer (HPET)
*/
- BOOL fHpetEnabled;
+ BOOL fHPETEnabled;
/* Other guests may wish to use HPET too, but MacOS X not functional without it */
- hrc = pMachine->COMGETTER(HpetEnabled)(&fHpetEnabled); H();
+ hrc = pMachine->COMGETTER(HPETEnabled)(&fHPETEnabled); H();
/* so always enable HPET in extended profile */
- fHpetEnabled |= fOsXGuest;
+ fHPETEnabled |= fOsXGuest;
/* HPET is always present on ICH9 */
- fHpetEnabled |= (chipsetType == ChipsetType_ICH9);
- if (fHpetEnabled)
+ fHPETEnabled |= (chipsetType == ChipsetType_ICH9);
+ if (fHPETEnabled)
{
InsertConfigNode(pDevices, "hpet", &pDev);
InsertConfigNode(pDev, "0", &pInst);
@@ -1165,7 +1200,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
{
InsertConfigNode(pDevices, "lpc", &pDev);
InsertConfigNode(pDev, "0", &pInst);
- hrc = BusMgr->assignPciDevice("lpc", pInst); H();
+ hrc = BusMgr->assignPCIDevice("lpc", pInst); H();
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
}
@@ -1261,7 +1296,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDev, "0", &pInst);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPciDevice("vga", pInst); H();
+ hrc = BusMgr->assignPCIDevice("vga", pInst); H();
InsertConfigNode(pInst, "Config", &pCfg);
ULONG cVRamMBs;
hrc = pMachine->COMGETTER(VRAMSize)(&cVRamMBs); H();
@@ -1478,6 +1513,14 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigInteger(pCfg, "DmiUseHostInfo", 1);
InsertConfigInteger(pCfg, "DmiExposeMemoryTable", 1);
}
+ PCFGMNODE pDrv;
+ InsertConfigNode(pInst, "LUN#0", &pLunL0);
+ InsertConfigString(pLunL0, "Driver", "NvramStorage");
+ InsertConfigNode(pLunL0, "Config", &pCfg);
+ InsertConfigInteger(pCfg, "Object", (uint64_t)mNvram);
+#ifdef DEBUG_vvl
+ InsertConfigInteger(pCfg, "PermanentSave", 1);
+#endif
}
/*
@@ -1532,7 +1575,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
{
case StorageControllerType_LsiLogic:
{
- hrc = BusMgr->assignPciDevice("lsilogic", pCtlInst); H();
+ hrc = BusMgr->assignPCIDevice("lsilogic", pCtlInst); H();
InsertConfigInteger(pCfg, "Bootable", fBootable);
@@ -1546,7 +1589,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
case StorageControllerType_BusLogic:
{
- hrc = BusMgr->assignPciDevice("buslogic", pCtlInst); H();
+ hrc = BusMgr->assignPCIDevice("buslogic", pCtlInst); H();
InsertConfigInteger(pCfg, "Bootable", fBootable);
@@ -1560,7 +1603,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
case StorageControllerType_IntelAhci:
{
- hrc = BusMgr->assignPciDevice("ahci", pCtlInst); H();
+ hrc = BusMgr->assignPCIDevice("ahci", pCtlInst); H();
ULONG cPorts = 0;
hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H();
@@ -1568,24 +1611,12 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigInteger(pCfg, "Bootable", fBootable);
/* Needed configuration values for the bios, only first controller. */
- if (!BusMgr->hasPciDevice("ahci", 1))
+ if (!BusMgr->hasPCIDevice("ahci", 1))
{
if (pBiosCfg)
{
InsertConfigString(pBiosCfg, "SataHardDiskDevice", "ahci");
}
-
- for (uint32_t j = 0; j < 4; ++j)
- {
- static const char * const s_apszBiosConfig[4] =
- { "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" };
-
- LONG lPortNumber = -1;
- hrc = ctrls[i]->GetIDEEmulationPort(j, &lPortNumber); H();
- InsertConfigInteger(pCfg, g_apszIDEDrives[j], lPortNumber);
- if (pBiosCfg)
- InsertConfigInteger(pBiosCfg, s_apszBiosConfig[j], lPortNumber);
- }
}
/* Attach the status driver */
@@ -1603,7 +1634,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
/*
* IDE (update this when the main interface changes)
*/
- hrc = BusMgr->assignPciDevice("piix3ide", pCtlInst); H();
+ hrc = BusMgr->assignPCIDevice("piix3ide", pCtlInst); H();
InsertConfigString(pCfg, "Type", controllerString(enmCtrlType));
/* Attach the status driver */
Assert(cLedIde >= 4);
@@ -1639,7 +1670,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
case StorageControllerType_LsiLogicSas:
{
- hrc = BusMgr->assignPciDevice("lsilogicsas", pCtlInst); H();
+ hrc = BusMgr->assignPCIDevice("lsilogicsas", pCtlInst); H();
InsertConfigString(pCfg, "ControllerType", "SAS1068");
InsertConfigInteger(pCfg, "Bootable", fBootable);
@@ -1662,8 +1693,8 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
ComSafeArrayAsOutParam(atts)); H();
/* Builtin I/O cache - per device setting. */
- BOOL fBuiltinIoCache = true;
- hrc = pMachine->COMGETTER(IoCacheEnabled)(&fBuiltinIoCache); H();
+ BOOL fBuiltinIOCache = true;
+ hrc = pMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache); H();
for (size_t j = 0; j < atts.size(); ++j)
@@ -1674,7 +1705,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
ulInstance,
enmBus,
!!fUseHostIOCache,
- !!fBuiltinIoCache,
+ !!fBuiltinIOCache,
false /* fSetupMerge */,
0 /* uMergeSource */,
0 /* uMergeTarget */,
@@ -1710,7 +1741,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDevices, "virtio-net", &pDevVirtioNet);
#endif /* VBOX_WITH_VIRTIO */
std::list<BootNic> llBootNics;
- for (ULONG ulInstance = 0; ulInstance < SchemaDefs::NetworkAdapterCount; ++ulInstance)
+ for (ULONG ulInstance = 0; ulInstance < maxNetworkAdapters; ++ulInstance)
{
ComPtr<INetworkAdapter> networkAdapter;
hrc = pMachine->GetNetworkAdapter(ulInstance, networkAdapter.asOutParam()); H();
@@ -1757,21 +1788,21 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
/* the first network card gets the PCI ID 3, the next 3 gets 8..10,
* next 4 get 16..19. */
- int iPciDeviceNo;
+ int iPCIDeviceNo;
switch (ulInstance)
{
case 0:
- iPciDeviceNo = 3;
+ iPCIDeviceNo = 3;
break;
case 1: case 2: case 3:
- iPciDeviceNo = ulInstance - 1 + 8;
+ iPCIDeviceNo = ulInstance - 1 + 8;
break;
case 4: case 5: case 6: case 7:
- iPciDeviceNo = ulInstance - 4 + 16;
+ iPCIDeviceNo = ulInstance - 4 + 16;
break;
default:
/* auto assignment */
- iPciDeviceNo = -1;
+ iPCIDeviceNo = -1;
break;
}
#ifdef VMWARE_NET_IN_SLOT_11
@@ -1779,19 +1810,19 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
* Dirty hack for PCI slot compatibility with VMWare,
* it assigns slot 11 to the first network controller.
*/
- if (iPciDeviceNo == 3 && adapterType == NetworkAdapterType_I82545EM)
+ if (iPCIDeviceNo == 3 && adapterType == NetworkAdapterType_I82545EM)
{
- iPciDeviceNo = 0x11;
+ iPCIDeviceNo = 0x11;
fSwapSlots3and11 = true;
}
- else if (iPciDeviceNo == 0x11 && fSwapSlots3and11)
- iPciDeviceNo = 3;
+ else if (iPCIDeviceNo == 0x11 && fSwapSlots3and11)
+ iPCIDeviceNo = 3;
#endif
- PciBusAddress PciAddr = PciBusAddress(0, iPciDeviceNo, 0);
- hrc = BusMgr->assignPciDevice(pszAdapterName, pInst, PciAddr); H();
+ PCIBusAddress PCIAddr = PCIBusAddress(0, iPCIDeviceNo, 0);
+ hrc = BusMgr->assignPCIDevice(pszAdapterName, pInst, PCIAddr); H();
InsertConfigNode(pInst, "Config", &pCfg);
-#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */
+#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */ /** @todo Make PCNet ring-0 safe on 32-bit mac kernels! */
if (pDev == pDevPCNet)
{
InsertConfigInteger(pCfg, "R0Enabled", false);
@@ -1804,7 +1835,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
nic.mInstance = ulInstance;
/* Could be updated by reference, if auto assigned */
- nic.mPciAddress = PciAddr;
+ nic.mPCIAddress = PCIAddr;
hrc = networkAdapter->COMGETTER(BootPriority)(&nic.mBootPrio); H();
@@ -1912,9 +1943,9 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
achBootIdx[0] = '0' + uBootIdx++; /* Boot device order. */
InsertConfigNode(pNetBootCfg, achBootIdx, &pNetBtDevCfg);
InsertConfigInteger(pNetBtDevCfg, "NIC", it->mInstance);
- InsertConfigInteger(pNetBtDevCfg, "PCIBusNo", it->mPciAddress.miBus);
- InsertConfigInteger(pNetBtDevCfg, "PCIDeviceNo", it->mPciAddress.miDevice);
- InsertConfigInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPciAddress.miFn);
+ InsertConfigInteger(pNetBtDevCfg, "PCIBusNo", it->mPCIAddress.miBus);
+ InsertConfigInteger(pNetBtDevCfg, "PCIDeviceNo", it->mPCIAddress.miDevice);
+ InsertConfigInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPCIAddress.miFn);
}
}
@@ -2009,7 +2040,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigInteger(pCfg, "IOBase", ulIOBase);
InsertConfigNode(pInst, "LUN#0", &pLunL0);
InsertConfigString(pLunL0, "Driver", "HostParallel");
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
+ InsertConfigNode(pLunL0, "Config", &pLunL1);
hrc = parallelPort->COMGETTER(Path)(bstr.asOutParam()); H();
InsertConfigString(pLunL1, "DevicePath", bstr);
}
@@ -2021,7 +2052,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDev, "0", &pInst);
InsertConfigNode(pInst, "Config", &pCfg);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPciDevice("VMMDev", pInst); H();
+ hrc = BusMgr->assignPCIDevice("VMMDev", pInst); H();
Bstr hwVersion;
hrc = pMachine->COMGETTER(HardwareVersion)(hwVersion.asOutParam()); H();
@@ -2078,7 +2109,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDevices, "ichac97", &pDev);
InsertConfigNode(pDev, "0", &pInst);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPciDevice("ichac97", pInst); H();
+ hrc = BusMgr->assignPCIDevice("ichac97", pInst); H();
InsertConfigNode(pInst, "Config", &pCfg);
break;
}
@@ -2102,7 +2133,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDevices, "hda", &pDev);
InsertConfigNode(pDev, "0", &pInst);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPciDevice("hda", pInst); H();
+ hrc = BusMgr->assignPCIDevice("hda", pInst); H();
InsertConfigNode(pInst, "Config", &pCfg);
}
}
@@ -2201,7 +2232,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDev, "0", &pInst);
InsertConfigNode(pInst, "Config", &pCfg);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPciDevice("usb-ohci", pInst); H();
+ hrc = BusMgr->assignPCIDevice("usb-ohci", pInst); H();
InsertConfigNode(pInst, "LUN#0", &pLunL0);
InsertConfigString(pLunL0, "Driver", "VUSBRootHub");
InsertConfigNode(pLunL0, "Config", &pCfg);
@@ -2212,9 +2243,9 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
attachStatusDriver(pInst, &mapUSBLed[0], 0, 0, NULL, NULL, 0);
#ifdef VBOX_WITH_EHCI
- BOOL fEhciEnabled;
- hrc = USBCtlPtr->COMGETTER(EnabledEhci)(&fEhciEnabled); H();
- if (fEhciEnabled)
+ BOOL fEHCIEnabled;
+ hrc = USBCtlPtr->COMGETTER(EnabledEHCI)(&fEHCIEnabled); H();
+ if (fEHCIEnabled)
{
/*
* USB 2.0 is only available if the proper ExtPack is installed.
@@ -2233,7 +2264,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDev, "0", &pInst);
InsertConfigNode(pInst, "Config", &pCfg);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPciDevice("usb-ehci", pInst); H();
+ hrc = BusMgr->assignPCIDevice("usb-ehci", pInst); H();
InsertConfigNode(pInst, "LUN#0", &pLunL0);
InsertConfigString(pLunL0, "Driver", "VUSBRootHub");
@@ -2348,15 +2379,15 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
# endif
/* Virtual USB Mouse/Tablet */
- PointingHidType_T aPointingHid;
- hrc = pMachine->COMGETTER(PointingHidType)(&aPointingHid); H();
- if (aPointingHid == PointingHidType_USBMouse || aPointingHid == PointingHidType_USBTablet)
+ PointingHIDType_T aPointingHID;
+ hrc = pMachine->COMGETTER(PointingHIDType)(&aPointingHID); H();
+ if (aPointingHID == PointingHIDType_USBMouse || aPointingHID == PointingHIDType_USBTablet)
{
InsertConfigNode(pUsbDevices, "HidMouse", &pDev);
InsertConfigNode(pDev, "0", &pInst);
InsertConfigNode(pInst, "Config", &pCfg);
- if (aPointingHid == PointingHidType_USBTablet)
+ if (aPointingHID == PointingHIDType_USBTablet)
{
InsertConfigInteger(pCfg, "Absolute", 1);
}
@@ -2377,9 +2408,9 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
}
/* Virtual USB Keyboard */
- KeyboardHidType_T aKbdHid;
- hrc = pMachine->COMGETTER(KeyboardHidType)(&aKbdHid); H();
- if (aKbdHid == KeyboardHidType_USBKeyboard)
+ KeyboardHIDType_T aKbdHID;
+ hrc = pMachine->COMGETTER(KeyboardHIDType)(&aKbdHID); H();
+ if (aKbdHID == KeyboardHIDType_USBKeyboard)
{
InsertConfigNode(pUsbDevices, "HidKeyboard", &pDev);
InsertConfigNode(pDev, "0", &pInst);
@@ -2406,7 +2437,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
ClipboardMode_T mode = ClipboardMode_Disabled;
hrc = pMachine->COMGETTER(ClipboardMode)(&mode); H();
- if (mode != ClipboardMode_Disabled)
+ if (/* mode != ClipboardMode_Disabled */ true)
{
/* Load the service */
rc = pVMMDev->hgcmLoadService("VBoxSharedClipboard", "VBoxSharedClipboard");
@@ -2419,50 +2450,74 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
}
else
{
+ changeClipboardMode(mode);
+
/* Setup the service. */
VBOXHGCMSVCPARM parm;
-
parm.type = VBOX_HGCM_SVC_PARM_32BIT;
+ parm.setUInt32(!useHostClipboard());
+ pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS, 1, &parm);
- switch (mode)
- {
- default:
- case ClipboardMode_Disabled:
- {
- LogRel(("VBoxSharedClipboard mode: Off\n"));
- parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF;
- break;
- }
- case ClipboardMode_GuestToHost:
- {
- LogRel(("VBoxSharedClipboard mode: Guest to Host\n"));
- parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST;
- break;
- }
- case ClipboardMode_HostToGuest:
- {
- LogRel(("VBoxSharedClipboard mode: Host to Guest\n"));
- parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST;
- break;
- }
- case ClipboardMode_Bidirectional:
- {
- LogRel(("VBoxSharedClipboard mode: Bidirectional\n"));
- parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL;
- break;
- }
- }
+ Log(("Set VBoxSharedClipboard mode\n"));
+ }
+ }
+ }
- pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
+ /*
+ * HGCM HostChannel
+ */
+ {
+ Bstr value;
+ hrc = pMachine->GetExtraData(Bstr("HGCM/HostChannel").raw(),
+ value.asOutParam());
- parm.setUInt32(!useHostClipboard());
+ if ( hrc == S_OK
+ && value == "1")
+ {
+ rc = pVMMDev->hgcmLoadService("VBoxHostChannel", "VBoxHostChannel");
- pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS, 1, &parm);
+ if (RT_FAILURE(rc))
+ {
+ LogRel(("VBoxHostChannel is not available. rc = %Rrc\n", rc));
+ /* That is not a fatal failure. */
+ rc = VINF_SUCCESS;
+ }
+ }
+ }
- Log(("Set VBoxSharedClipboard mode\n"));
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ /*
+ * Drag & Drop
+ */
+ {
+ DragAndDropMode_T mode = DragAndDropMode_Disabled;
+ hrc = pMachine->COMGETTER(DragAndDropMode)(&mode); H();
+
+ /* Load the service */
+ rc = pVMMDev->hgcmLoadService("VBoxDragAndDropSvc", "VBoxDragAndDropSvc");
+
+ if (RT_FAILURE(rc))
+ {
+ LogRel(("VBoxDragAndDropService is not available. rc = %Rrc\n", rc));
+ /* That is not a fatal failure. */
+ rc = VINF_SUCCESS;
+ }
+ else
+ {
+ HGCMSVCEXTHANDLE hDummy;
+ rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxDragAndDropSvc",
+ &GuestDnD::notifyGuestDragAndDropEvent,
+ getGuest());
+ if (RT_FAILURE(rc))
+ Log(("Cannot register VBoxDragAndDropSvc extension!\n"));
+ else
+ {
+ changeDragAndDropMode(mode);
+ Log(("VBoxDragAndDropSvc loaded\n"));
}
}
}
+#endif /* VBOX_WITH_DRAG_AND_DROP */
#ifdef VBOX_WITH_CROGL
/*
@@ -2522,7 +2577,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
* Guest property service
*/
- rc = configGuestProperties(this);
+ rc = configGuestProperties(this, pVM);
#endif /* VBOX_WITH_GUEST_PROPS defined */
#ifdef VBOX_WITH_GUEST_CONTROL
@@ -2555,7 +2610,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigNode(pDev, "0", &pInst);
InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
InsertConfigNode(pInst, "Config", &pCfg);
- hrc = BusMgr->assignPciDevice("acpi", pInst); H();
+ hrc = BusMgr->assignPCIDevice("acpi", pInst); H();
InsertConfigInteger(pCfg, "RamSize", cbRam);
InsertConfigInteger(pCfg, "RamHoleSize", cbRamHole);
@@ -2563,31 +2618,31 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC);
InsertConfigInteger(pCfg, "FdcEnabled", fFdcEnabled);
- InsertConfigInteger(pCfg, "HpetEnabled", fHpetEnabled);
+ InsertConfigInteger(pCfg, "HpetEnabled", fHPETEnabled);
InsertConfigInteger(pCfg, "SmcEnabled", fSmcEnabled);
InsertConfigInteger(pCfg, "ShowRtc", fShowRtc);
if (fOsXGuest && !llBootNics.empty())
{
BootNic aNic = llBootNics.front();
- uint32_t u32NicPciAddr = (aNic.mPciAddress.miDevice << 16) | aNic.mPciAddress.miFn;
- InsertConfigInteger(pCfg, "NicPciAddress", u32NicPciAddr);
+ uint32_t u32NicPCIAddr = (aNic.mPCIAddress.miDevice << 16) | aNic.mPCIAddress.miFn;
+ InsertConfigInteger(pCfg, "NicPciAddress", u32NicPCIAddr);
}
if (fOsXGuest && fAudioEnabled)
{
- PciBusAddress Address;
- if (BusMgr->findPciAddress("hda", 0, Address))
+ PCIBusAddress Address;
+ if (BusMgr->findPCIAddress("hda", 0, Address))
{
- uint32_t u32AudioPciAddr = (Address.miDevice << 16) | Address.miFn;
- InsertConfigInteger(pCfg, "AudioPciAddress", u32AudioPciAddr);
+ uint32_t u32AudioPCIAddr = (Address.miDevice << 16) | Address.miFn;
+ InsertConfigInteger(pCfg, "AudioPciAddress", u32AudioPCIAddr);
}
}
- InsertConfigInteger(pCfg, "IocPciAddress", uIocPciAddress);
+ InsertConfigInteger(pCfg, "IocPciAddress", uIocPCIAddress);
if (chipsetType == ChipsetType_ICH9)
{
InsertConfigInteger(pCfg, "McfgBase", uMcfgBase);
InsertConfigInteger(pCfg, "McfgLength", cbMcfgLength);
}
- InsertConfigInteger(pCfg, "HostBusPciAddress", uHbcPciAddress);
+ InsertConfigInteger(pCfg, "HostBusPciAddress", uHbcPCIAddress);
InsertConfigInteger(pCfg, "ShowCpu", fShowCpu);
InsertConfigInteger(pCfg, "CpuHotPlug", fCpuHotPlug);
@@ -2619,6 +2674,47 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
}
}
}
+
+ /*
+ * Configure DBGF (Debug(ger) Facility).
+ */
+ {
+ PCFGMNODE pDbgf;
+ InsertConfigNode(pRoot, "DBGF", &pDbgf);
+
+ /* Paths to search for debug info and such things. */
+ hrc = pMachine->COMGETTER(SettingsFilePath)(bstr.asOutParam()); H();
+ Utf8Str strSettingsPath(bstr);
+ bstr.setNull();
+ strSettingsPath.stripFilename();
+
+ char szHomeDir[RTPATH_MAX];
+ rc = RTPathUserHome(szHomeDir, sizeof(szHomeDir));
+ if (RT_FAILURE(rc))
+ szHomeDir[0] = '\0';
+
+ Utf8Str strPath;
+ strPath.append(strSettingsPath).append("/debug/;");
+ strPath.append(strSettingsPath).append("/;");
+ strPath.append(szHomeDir).append("/");
+
+ InsertConfigString(pDbgf, "Path", strPath.c_str());
+
+ /* Tracing configuration. */
+ BOOL fTracingEnabled;
+ hrc = pMachine->COMGETTER(TracingEnabled)(&fTracingEnabled); H();
+ if (fTracingEnabled)
+ InsertConfigInteger(pDbgf, "TracingEnabled", 1);
+
+ hrc = pMachine->COMGETTER(TracingConfig)(bstr.asOutParam()); H();
+ if (fTracingEnabled)
+ InsertConfigString(pDbgf, "TracingConfig", bstr);
+
+ BOOL fAllowTracingToAccessVM;
+ hrc = pMachine->COMGETTER(AllowTracingToAccessVM)(&fAllowTracingToAccessVM); H();
+ if (fAllowTracingToAccessVM)
+ InsertConfigInteger(pPDM, "AllowTracingToAccessVM", 1);
+ }
}
catch (ConfigError &x)
{
@@ -2644,6 +2740,12 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
if (RT_SUCCESS(rc))
rc = configCfgmOverlay(pVM, virtualBox, pMachine);
+ /*
+ * Dump all extradata API settings tweaks, both global and per VM.
+ */
+ if (RT_SUCCESS(rc))
+ rc = configDumpAPISettingsTweaks(virtualBox, pMachine);
+
#undef H
pAlock->release(); /* Avoid triggering the lock order inversion check. */
@@ -2673,7 +2775,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
}
/**
- * Applies the CFGM overlay as specified by /VBoxInternal/XXX extra data
+ * Applies the CFGM overlay as specified by VBoxInternal/XXX extra data
* values.
*
* @returns VBox status code.
@@ -2714,7 +2816,7 @@ int Console::configCfgmOverlay(PVM pVM, IVirtualBox *pVirtualBox, IMachine *pMac
size_t cGlobalValues = aGlobalExtraDataKeys.size();
hrc = pMachine->GetExtraDataKeys(ComSafeArrayAsOutParam(aMachineExtraDataKeys));
- AssertMsg(SUCCEEDED(hrc), ("VirtualBox::GetExtraDataKeys failed with %Rhrc\n", hrc));
+ AssertMsg(SUCCEEDED(hrc), ("Machine::GetExtraDataKeys failed with %Rhrc\n", hrc));
// build a combined list from global keys...
std::list<Utf8Str> llExtraDataKeys;
@@ -2830,6 +2932,66 @@ int Console::configCfgmOverlay(PVM pVM, IVirtualBox *pVirtualBox, IMachine *pMac
}
/**
+ * Dumps the API settings tweaks as specified by VBoxInternal2/XXX extra data
+ * values.
+ *
+ * @returns VBox status code.
+ * @param pVirtualBox Pointer to the IVirtualBox interface.
+ * @param pMachine Pointer to the IMachine interface.
+ */
+/* static */
+int Console::configDumpAPISettingsTweaks(IVirtualBox *pVirtualBox, IMachine *pMachine)
+{
+ {
+ SafeArray<BSTR> aGlobalExtraDataKeys;
+ HRESULT hrc = pVirtualBox->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys));
+ AssertMsg(SUCCEEDED(hrc), ("VirtualBox::GetExtraDataKeys failed with %Rhrc\n", hrc));
+ bool hasKey = false;
+ for (size_t i = 0; i < aGlobalExtraDataKeys.size(); i++)
+ {
+ Utf8Str strKey(aGlobalExtraDataKeys[i]);
+ if (!strKey.startsWith("VBoxInternal2/"))
+ continue;
+
+ Bstr bstrValue;
+ hrc = pVirtualBox->GetExtraData(Bstr(strKey).raw(),
+ bstrValue.asOutParam());
+ if (FAILED(hrc))
+ continue;
+ if (!hasKey)
+ LogRel(("Global extradata API settings:\n"));
+ LogRel((" %s=\"%ls\"\n", strKey.c_str(), bstrValue.raw()));
+ hasKey = true;
+ }
+ }
+
+ {
+ SafeArray<BSTR> aMachineExtraDataKeys;
+ HRESULT hrc = pMachine->GetExtraDataKeys(ComSafeArrayAsOutParam(aMachineExtraDataKeys));
+ AssertMsg(SUCCEEDED(hrc), ("Machine::GetExtraDataKeys failed with %Rhrc\n", hrc));
+ bool hasKey = false;
+ for (size_t i = 0; i < aMachineExtraDataKeys.size(); i++)
+ {
+ Utf8Str strKey(aMachineExtraDataKeys[i]);
+ if (!strKey.startsWith("VBoxInternal2/"))
+ continue;
+
+ Bstr bstrValue;
+ hrc = pMachine->GetExtraData(Bstr(strKey).raw(),
+ bstrValue.asOutParam());
+ if (FAILED(hrc))
+ continue;
+ if (!hasKey)
+ LogRel(("Per-VM extradata API settings:\n"));
+ LogRel((" %s=\"%ls\"\n", strKey.c_str(), bstrValue.raw()));
+ hasKey = true;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+/**
* Ellipsis to va_list wrapper for calling setVMRuntimeErrorCallback.
*/
/*static*/
@@ -2866,7 +3028,7 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
unsigned uInstance,
StorageBus_T enmBus,
bool fUseHostIOCache,
- bool fBuiltinIoCache,
+ bool fBuiltinIOCache,
bool fSetupMerge,
unsigned uMergeSource,
unsigned uMergeTarget,
@@ -2897,6 +3059,8 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
hrc = pMediumAtt->COMGETTER(Type)(&lType); H();
BOOL fNonRotational;
hrc = pMediumAtt->COMGETTER(NonRotational)(&fNonRotational); H();
+ BOOL fDiscard;
+ hrc = pMediumAtt->COMGETTER(Discard)(&fDiscard); H();
unsigned uLUN;
PCFGMNODE pLunL0 = NULL;
@@ -2972,7 +3136,6 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
InsertConfigInteger(pDrive, "NonRotationalMedium", !!fNonRotational);
}
}
- /** @todo add SCSI/SAS support once the SSD support is there */
Utf8Str devicePath = Utf8StrFmt("%s/%u/LUN#%u", pcszDevice, uInstance, uLUN);
mapMediumAttachments[devicePath] = pMediumAtt;
@@ -2983,6 +3146,7 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
InsertConfigString(pLunL0, "Driver", "SCSI");
PCFGMNODE pL1Cfg = NULL;
InsertConfigNode(pLunL0, "Config", &pL1Cfg);
+ InsertConfigInteger(pL1Cfg, "NonRotationalMedium", !!fNonRotational);
InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
}
@@ -3025,7 +3189,8 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
(void)RTFsQueryType(utfSnap.c_str(), &enmFsTypeSnap);
if (!mfSnapshotFolderDiskTypeShown)
{
- LogRel(("File system of '%s' (snapshots) is %s\n", utfSnap.c_str(), RTFsTypeName(enmFsTypeSnap)));
+ LogRel(("File system of '%s' (snapshots) is %s\n",
+ utfSnap.c_str(), RTFsTypeName(enmFsTypeSnap)));
mfSnapshotFolderDiskTypeShown = true;
}
LogRel(("File system of '%s' is %s\n", utfFile.c_str(), RTFsTypeName(enmFsTypeFile)));
@@ -3173,6 +3338,30 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
}
}
+ if ( pMedium
+ && ( lType == DeviceType_DVD
+ || lType == DeviceType_Floppy))
+ {
+ /*
+ * Informative logging.
+ */
+ ComPtr<IMediumFormat> pMediumFormat;
+ hrc = pMedium->COMGETTER(MediumFormat)(pMediumFormat.asOutParam()); H();
+ ULONG uCaps;
+ hrc = pMediumFormat->COMGETTER(Capabilities)(&uCaps); H();
+ if (uCaps & MediumFormatCapabilities_File)
+ {
+ Bstr strFile;
+ hrc = pMedium->COMGETTER(Location)(strFile.asOutParam()); H();
+ Utf8Str utfFile = Utf8Str(strFile);
+ RTFSTYPE enmFsTypeFile = RTFSTYPE_UNKNOWN;
+ (void)RTFsQueryType(utfFile.c_str(), &enmFsTypeFile);
+ LogRel(("File system of '%s' (%s) is %s\n",
+ utfFile.c_str(), lType == DeviceType_DVD ? "DVD" : "Floppy",
+ RTFsTypeName(enmFsTypeFile)));
+ }
+ }
+
BOOL fPassthrough;
hrc = pMediumAtt->COMGETTER(Passthrough)(&fPassthrough); H();
@@ -3189,11 +3378,12 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
!!fPassthrough,
lType,
fUseHostIOCache,
- fBuiltinIoCache,
+ fBuiltinIOCache,
fSetupMerge,
uMergeSource,
uMergeTarget,
strBwGroup.isEmpty() ? NULL : Utf8Str(strBwGroup).c_str(),
+ !!fDiscard,
pMedium,
aMachineState,
phrc);
@@ -3230,11 +3420,12 @@ int Console::configMedium(PCFGMNODE pLunL0,
bool fPassthrough,
DeviceType_T enmType,
bool fUseHostIOCache,
- bool fBuiltinIoCache,
+ bool fBuiltinIOCache,
bool fSetupMerge,
unsigned uMergeSource,
unsigned uMergeTarget,
const char *pcszBwGroup,
+ bool fDiscard,
IMedium *pMedium,
MachineState_T aMachineState,
HRESULT *phrc)
@@ -3394,7 +3585,7 @@ int Console::configMedium(PCFGMNODE pLunL0,
* It caches writes only which doesn't make sense for DVD drives
* and just increases the overhead.
*/
- if ( fBuiltinIoCache
+ if ( fBuiltinIOCache
&& (enmType == DeviceType_HardDisk))
InsertConfigInteger(pCfg, "BlockCache", 1);
}
@@ -3424,6 +3615,9 @@ int Console::configMedium(PCFGMNODE pLunL0,
if (pcszBwGroup)
InsertConfigString(pCfg, "BwGroup", pcszBwGroup);
+ if (fDiscard)
+ InsertConfigInteger(pCfg, "Discard", 1);
+
/* Pass all custom parameters. */
bool fHostIP = true;
SafeArray<BSTR> names;
@@ -3597,46 +3791,7 @@ int Console::configNetwork(const char *pszDevice,
default: AssertFailedReturn(VERR_INTERNAL_ERROR_4);
}
- Utf8Str strNetDriver;
- if (fAttachDetach && fSniffer)
- {
- const char *pszNetDriver = "IntNet";
- if (meAttachmentType[uInstance] == NetworkAttachmentType_NAT)
- pszNetDriver = "NAT";
-#if !defined(VBOX_WITH_NETFLT) && defined(RT_OS_LINUX)
- if (meAttachmentType[uInstance] == NetworkAttachmentType_Bridged)
- pszNetDriver = "HostInterface";
-#endif
- if (meAttachmentType[uInstance] == NetworkAttachmentType_Generic)
- {
- hrc = aNetworkAdapter->COMGETTER(GenericDriver)(bstr.asOutParam()); H();
- strNetDriver = bstr;
- pszNetDriver = strNetDriver.c_str();
- }
-
- rc = PDMR3DriverDetach(pVM, pszDevice, uInstance, uLun, pszNetDriver, 0, 0 /*fFlags*/);
- if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN)
- rc = VINF_SUCCESS;
- AssertLogRelRCReturn(rc, rc);
-
- pLunL0 = CFGMR3GetChildF(pInst, "LUN#%u", uLun);
- PCFGMNODE pLunAD = CFGMR3GetChildF(pLunL0, "AttachedDriver");
- if (pLunAD)
- {
- CFGMR3RemoveNode(pLunAD);
- }
- else
- {
- CFGMR3RemoveNode(pLunL0);
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
- InsertConfigString(pLunL0, "Driver", "NetSniffer");
- InsertConfigNode(pLunL0, "Config", &pCfg);
- hrc = aNetworkAdapter->COMGETTER(TraceFile)(bstr.asOutParam()); H();
- if (!bstr.isEmpty()) /* check convention for indicating default file. */
- InsertConfigString(pCfg, "File", bstr);
- }
- }
- else if (fAttachDetach && !fSniffer)
+ if (fAttachDetach)
{
rc = PDMR3DeviceDetach(pVM, pszDevice, uInstance, uLun, 0 /*fFlags*/);
if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN)
@@ -3646,17 +3801,44 @@ int Console::configNetwork(const char *pszDevice,
/* nuke anything which might have been left behind. */
CFGMR3RemoveNode(CFGMR3GetChildF(pInst, "LUN#%u", uLun));
}
- else if (!fAttachDetach && fSniffer)
+
+#ifdef VBOX_WITH_NETSHAPER
+ ComObjPtr<IBandwidthGroup> pBwGroup;
+ Bstr strBwGroup;
+ hrc = aNetworkAdapter->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam()); H();
+
+ if (!pBwGroup.isNull())
+ {
+ hrc = pBwGroup->COMGETTER(Name)(strBwGroup.asOutParam()); H();
+ }
+#endif /* VBOX_WITH_NETSHAPER */
+
+ Utf8Str strNetDriver;
+
+
+ InsertConfigNode(pInst, "LUN#0", &pLunL0);
+
+#ifdef VBOX_WITH_NETSHAPER
+ if (!strBwGroup.isEmpty())
+ {
+ InsertConfigString(pLunL0, "Driver", "NetShaper");
+ InsertConfigNode(pLunL0, "Config", &pCfg);
+ InsertConfigString(pCfg, "BwGroup", strBwGroup);
+ InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
+ }
+#endif /* VBOX_WITH_NETSHAPER */
+
+ if (fSniffer)
{
- /* insert the sniffer filter driver. */
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
InsertConfigString(pLunL0, "Driver", "NetSniffer");
InsertConfigNode(pLunL0, "Config", &pCfg);
- hrc = aNetworkAdapter->COMGETTER(TraceFile)(bstr.asOutParam()); H();
+ hrc = aNetworkAdapter->COMGETTER(TraceFile)(bstr.asOutParam()); H();
if (!bstr.isEmpty()) /* check convention for indicating default file. */
InsertConfigString(pCfg, "File", bstr);
+ InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
}
+
Bstr networkName, trunkName, trunkType;
NetworkAttachmentType_T eAttachmentType;
hrc = aNetworkAdapter->COMGETTER(AttachmentType)(&eAttachmentType); H();
@@ -3667,12 +3849,8 @@ int Console::configNetwork(const char *pszDevice,
case NetworkAttachmentType_NAT:
{
- ComPtr<INATEngine> natDriver;
- hrc = aNetworkAdapter->COMGETTER(NatDriver)(natDriver.asOutParam()); H();
- if (fSniffer)
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
- else
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
+ ComPtr<INATEngine> natEngine;
+ hrc = aNetworkAdapter->COMGETTER(NATEngine)(natEngine.asOutParam()); H();
InsertConfigString(pLunL0, "Driver", "NAT");
InsertConfigNode(pLunL0, "Config", &pCfg);
@@ -3683,7 +3861,7 @@ int Console::configNetwork(const char *pszDevice,
hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H();
InsertConfigString(pCfg, "BootFile", Utf8StrFmt("%ls.pxe", bstr.raw()));
- hrc = natDriver->COMGETTER(Network)(bstr.asOutParam()); H();
+ hrc = natEngine->COMGETTER(Network)(bstr.asOutParam()); H();
if (!bstr.isEmpty())
InsertConfigString(pCfg, "Network", bstr);
else
@@ -3692,7 +3870,7 @@ int Console::configNetwork(const char *pszDevice,
hrc = aNetworkAdapter->COMGETTER(Slot)(&uSlot); H();
InsertConfigString(pCfg, "Network", Utf8StrFmt("10.0.%d.0/24", uSlot+2));
}
- hrc = natDriver->COMGETTER(HostIP)(bstr.asOutParam()); H();
+ hrc = natEngine->COMGETTER(HostIP)(bstr.asOutParam()); H();
if (!bstr.isEmpty())
InsertConfigString(pCfg, "BindIP", bstr);
ULONG mtu = 0;
@@ -3700,7 +3878,7 @@ int Console::configNetwork(const char *pszDevice,
ULONG sockRcv = 0;
ULONG tcpSnd = 0;
ULONG tcpRcv = 0;
- hrc = natDriver->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv); H();
+ hrc = natEngine->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv); H();
if (mtu)
InsertConfigInteger(pCfg, "SlirpMTU", mtu);
if (sockRcv)
@@ -3711,36 +3889,36 @@ int Console::configNetwork(const char *pszDevice,
InsertConfigInteger(pCfg, "TcpRcv", tcpRcv);
if (tcpSnd)
InsertConfigInteger(pCfg, "TcpSnd", tcpSnd);
- hrc = natDriver->COMGETTER(TftpPrefix)(bstr.asOutParam()); H();
+ hrc = natEngine->COMGETTER(TFTPPrefix)(bstr.asOutParam()); H();
if (!bstr.isEmpty())
{
RemoveConfigValue(pCfg, "TFTPPrefix");
InsertConfigString(pCfg, "TFTPPrefix", bstr);
}
- hrc = natDriver->COMGETTER(TftpBootFile)(bstr.asOutParam()); H();
+ hrc = natEngine->COMGETTER(TFTPBootFile)(bstr.asOutParam()); H();
if (!bstr.isEmpty())
{
RemoveConfigValue(pCfg, "BootFile");
InsertConfigString(pCfg, "BootFile", bstr);
}
- hrc = natDriver->COMGETTER(TftpNextServer)(bstr.asOutParam()); H();
+ hrc = natEngine->COMGETTER(TFTPNextServer)(bstr.asOutParam()); H();
if (!bstr.isEmpty())
InsertConfigString(pCfg, "NextServer", bstr);
- BOOL fDnsFlag;
- hrc = natDriver->COMGETTER(DnsPassDomain)(&fDnsFlag); H();
- InsertConfigInteger(pCfg, "PassDomain", fDnsFlag);
- hrc = natDriver->COMGETTER(DnsProxy)(&fDnsFlag); H();
- InsertConfigInteger(pCfg, "DNSProxy", fDnsFlag);
- hrc = natDriver->COMGETTER(DnsUseHostResolver)(&fDnsFlag); H();
- InsertConfigInteger(pCfg, "UseHostResolver", fDnsFlag);
+ BOOL fDNSFlag;
+ hrc = natEngine->COMGETTER(DNSPassDomain)(&fDNSFlag); H();
+ InsertConfigInteger(pCfg, "PassDomain", fDNSFlag);
+ hrc = natEngine->COMGETTER(DNSProxy)(&fDNSFlag); H();
+ InsertConfigInteger(pCfg, "DNSProxy", fDNSFlag);
+ hrc = natEngine->COMGETTER(DNSUseHostResolver)(&fDNSFlag); H();
+ InsertConfigInteger(pCfg, "UseHostResolver", fDNSFlag);
ULONG aliasMode;
- hrc = natDriver->COMGETTER(AliasMode)(&aliasMode); H();
+ hrc = natEngine->COMGETTER(AliasMode)(&aliasMode); H();
InsertConfigInteger(pCfg, "AliasMode", aliasMode);
/* port-forwarding */
SafeArray<BSTR> pfs;
- hrc = natDriver->COMGETTER(Redirects)(ComSafeArrayAsOutParam(pfs)); H();
+ hrc = natEngine->COMGETTER(Redirects)(ComSafeArrayAsOutParam(pfs)); H();
PCFGMNODE pPF = NULL; /* /Devices/Dev/.../Config/PF#0/ */
for (unsigned int i = 0; i < pfs.size(); ++i)
{
@@ -3837,14 +4015,6 @@ int Console::configNetwork(const char *pszDevice,
Assert((int)maTapFD[uInstance] >= 0);
if ((int)maTapFD[uInstance] >= 0)
{
- if (fSniffer)
- {
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
- }
- else
- {
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
- }
InsertConfigString(pLunL0, "Driver", "HostInterface");
InsertConfigNode(pLunL0, "Config", &pCfg);
InsertConfigInteger(pCfg, "FileHandle", maTapFD[uInstance]);
@@ -3854,15 +4024,6 @@ int Console::configNetwork(const char *pszDevice,
/*
* This is the new VBoxNetFlt+IntNet stuff.
*/
- if (fSniffer)
- {
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
- }
- else
- {
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
- }
-
Bstr BridgedIfName;
hrc = aNetworkAdapter->COMGETTER(BridgedInterface)(BridgedIfName.asOutParam());
if (FAILED(hrc))
@@ -3879,14 +4040,14 @@ int Console::configNetwork(const char *pszDevice,
char szTrunk[8];
RTStrCopy(szTrunk, sizeof(szTrunk), pszBridgedIfName);
char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));
-// Quick fix for #5633
+// Quick fix for @bugref{5633}
// if (!pszColon)
// {
// /*
// * Dynamic changing of attachment causes an attempt to configure
// * network with invalid host adapter (as it is must be changed before
// * the attachment), calling Detach here will cause a deadlock.
-// * See #4750.
+// * See @bugref{4750}.
// * hrc = aNetworkAdapter->Detach(); H();
// */
// return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,
@@ -4092,7 +4253,17 @@ int Console::configNetwork(const char *pszDevice,
InsertConfigInteger(pCfg, "IgnoreConnectFailure", (uint64_t)fIgnoreConnectFailure);
InsertConfigString(pCfg, "IfPolicyPromisc", pszPromiscuousGuestPolicy);
char szNetwork[INTNET_MAX_NETWORK_NAME];
+
+#if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN)
+ /*
+ * 'pszTrunk' contains just the interface name required in ring-0, while 'pszBridgedIfName' contains
+ * interface name + optional description. We must not pass any description to the VM as it can differ
+ * for the same interface name, eg: "nge0 - ethernet" (GUI) vs "nge0" (VBoxManage).
+ */
+ RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszTrunk);
+#else
RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszBridgedIfName);
+#endif
InsertConfigString(pCfg, "Network", szNetwork);
networkName = Bstr(szNetwork);
trunkName = Bstr(pszTrunk);
@@ -4254,10 +4425,6 @@ int Console::configNetwork(const char *pszDevice,
hrc = aNetworkAdapter->COMGETTER(InternalNetwork)(bstr.asOutParam()); H();
if (!bstr.isEmpty())
{
- if (fSniffer)
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
- else
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
InsertConfigString(pLunL0, "Driver", "IntNet");
InsertConfigNode(pLunL0, "Config", &pCfg);
InsertConfigString(pCfg, "Network", bstr);
@@ -4271,11 +4438,6 @@ int Console::configNetwork(const char *pszDevice,
case NetworkAttachmentType_HostOnly:
{
- if (fSniffer)
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
- else
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
-
InsertConfigString(pLunL0, "Driver", "IntNet");
InsertConfigNode(pLunL0, "Config", &pCfg);
@@ -4442,16 +4604,16 @@ int Console::configNetwork(const char *pszDevice,
pszHostOnlyName).raw(),
tmpMask.asOutParam());
if (SUCCEEDED(hrc) && !tmpMask.isEmpty())
- hrc = hostInterface->EnableStaticIpConfig(tmpAddr.raw(),
+ hrc = hostInterface->EnableStaticIPConfig(tmpAddr.raw(),
tmpMask.raw());
else
- hrc = hostInterface->EnableStaticIpConfig(tmpAddr.raw(),
+ hrc = hostInterface->EnableStaticIPConfig(tmpAddr.raw(),
Bstr(VBOXNET_IPV4MASK_DEFAULT).raw());
}
else
{
/* Grab the IP number from the 'vboxnetX' instance number (see netif.h) */
- hrc = hostInterface->EnableStaticIpConfig(getDefaultIPv4Address(Bstr(pszHostOnlyName)).raw(),
+ hrc = hostInterface->EnableStaticIPConfig(getDefaultIPv4Address(Bstr(pszHostOnlyName)).raw(),
Bstr(VBOXNET_IPV4MASK_DEFAULT).raw());
}
@@ -4465,7 +4627,7 @@ int Console::configNetwork(const char *pszDevice,
tmpMask.asOutParam());
if (SUCCEEDED(hrc) && !tmpAddr.isEmpty() && !tmpMask.isEmpty())
{
- hrc = hostInterface->EnableStaticIpConfigV6(tmpAddr.raw(),
+ hrc = hostInterface->EnableStaticIPConfigV6(tmpAddr.raw(),
Utf8Str(tmpMask).toUInt32());
ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */
}
@@ -4482,10 +4644,6 @@ int Console::configNetwork(const char *pszDevice,
ComSafeArrayAsOutParam(names),
ComSafeArrayAsOutParam(values)); H();
- if (fSniffer)
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0);
- else
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
InsertConfigString(pLunL0, "Driver", bstr);
InsertConfigNode(pLunL0, "Config", &pCfg);
for (size_t ii = 0; ii < names.size(); ++ii)
@@ -4675,7 +4833,7 @@ int configSetGlobalPropertyFlags(VMMDev * const pVMMDev,
* Set up the Guest Property service, populate it with properties read from
* the machine XML and set a couple of initial properties.
*/
-/* static */ int Console::configGuestProperties(void *pvConsole)
+/* static */ int Console::configGuestProperties(void *pvConsole, PVM pVM)
{
#ifdef VBOX_WITH_GUEST_PROPS
AssertReturn(pvConsole, VERR_GENERAL_FAILURE);
@@ -4700,6 +4858,17 @@ int configSetGlobalPropertyFlags(VMMDev * const pVMMDev,
* change.
*/
+ {
+ VBOXHGCMSVCPARM Params[2];
+ int rc2 = pConsole->m_pVMMDev->hgcmHostCall("VBoxGuestPropSvc", guestProp::GET_DBGF_INFO_FN, 2, &Params[0]);
+ if (RT_SUCCESS(rc2))
+ {
+ PFNDBGFHANDLEREXT pfnHandler = (PFNDBGFHANDLEREXT)(uintptr_t)Params[0].u.pointer.addr;
+ void *pService = (void*)Params[1].u.pointer.addr;
+ DBGFR3InfoRegisterExternal(pVM, "guestprops", "Display the guest properties", pfnHandler, pService);
+ }
+ }
+
/* Sysprep execution by VBoxService. */
configSetProperty(pConsole->m_pVMMDev,
"/VirtualBox/HostGuest/SysprepExec", "",
diff --git a/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp b/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp
index d5f4561eb..7e765352c 100644
--- a/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp
+++ b/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -25,6 +25,7 @@
#include "AutoCaller.h"
#include "Logging.h"
+#include "HashedPw.h"
#include <iprt/asm.h>
#include <iprt/err.h>
@@ -884,10 +885,10 @@ Console::teleporterSrcThreadWrapper(RTTHREAD hThread, void *pvUser)
pState->mptrConsole->setMachineState(MachineState_Paused);
if (pState->mfSuspendedByUs)
{
- autoLock.leave();
+ autoLock.release();
int rc = VMR3Resume(VMR3GetVM(pState->mpUVM));
AssertLogRelMsgRC(rc, ("VMR3Resume -> %Rrc\n", rc));
- autoLock.enter();
+ autoLock.acquire();
}
}
else
@@ -899,7 +900,7 @@ Console::teleporterSrcThreadWrapper(RTTHREAD hThread, void *pvUser)
}
}
}
- autoLock.leave();
+ autoLock.release();
/*
* Cleanup.
@@ -931,10 +932,18 @@ Console::Teleport(IN_BSTR aHostname, ULONG aPort, IN_BSTR aPassword, ULONG aMaxD
*/
CheckComArgOutPointerValid(aProgress);
CheckComArgStrNotEmptyOrNull(aHostname);
- CheckComArgStrNotEmptyOrNull(aHostname);
+ CheckComArgStrNotEmptyOrNull(aPassword);
CheckComArgExprMsg(aPort, aPort > 0 && aPort <= 65535, ("is %u", aPort));
CheckComArgExprMsg(aMaxDowntime, aMaxDowntime > 0, ("is %u", aMaxDowntime));
+ Utf8Str strPassword(aPassword);
+ if (!strPassword.isEmpty())
+ {
+ if (VBoxIsPasswordHashed(&strPassword))
+ return setError(E_INVALIDARG, tr("The specified password resembles a hashed password, expected plain text"));
+ VBoxHashPassword(&strPassword);
+ }
+
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -970,7 +979,7 @@ Console::Teleport(IN_BSTR aHostname, ULONG aPort, IN_BSTR aPassword, ULONG aMaxD
return hrc;
TeleporterStateSrc *pState = new TeleporterStateSrc(this, mpUVM, ptrProgress, mMachineState);
- pState->mstrPassword = aPassword;
+ pState->mstrPassword = strPassword;
pState->mstrHostname = aHostname;
pState->muPort = aPort;
pState->mcMsMaxDowntime = aMaxDowntime;
diff --git a/src/VBox/Main/src-client/ConsoleVRDPServer.cpp b/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
index b3735bb27..4ba75ad65 100644
--- a/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
+++ b/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -373,6 +373,15 @@ STDMETHODIMP VRDPConsoleListener::OnMousePointerShapeChange(BOOL visible,
}
else if (width != 0 && height != 0)
{
+ uint8_t* shape = aShape.raw();
+
+ dumpPointer(shape, width, height, true);
+
+ if (m_server->MousePointer(alpha, xHot, yHot, width, height, shape) == VINF_SUCCESS)
+ {
+ return S_OK;
+ }
+
/* Pointer consists of 1 bpp AND and 24 BPP XOR masks.
* 'shape' AND mask followed by XOR mask.
* XOR mask contains 32 bit (lsb)BGR0(msb) values.
@@ -389,9 +398,6 @@ STDMETHODIMP VRDPConsoleListener::OnMousePointerShapeChange(BOOL visible,
* So set pointer size to 32x32. This can be done safely
* because most pointers are 32x32.
*/
- uint8_t* shape = aShape.raw();
-
- dumpPointer(shape, width, height, true);
int cbDstAndMask = (((width + 7) / 8) * height + 3) & ~3;
@@ -1258,7 +1264,9 @@ DECLCALLBACK(void) ConsoleVRDPServer::VRDPCallbackVideoModeHint(void *pvCallback
{
ConsoleVRDPServer *server = static_cast<ConsoleVRDPServer*>(pvCallback);
- server->mConsole->getDisplay()->SetVideoModeHint(cWidth, cHeight, cBitsPerPixel, uScreenId);
+ server->mConsole->getDisplay()->SetVideoModeHint(uScreenId, TRUE /*=enabled*/,
+ FALSE /*=changeOrigin*/, 0/*=OriginX*/, 0/*=OriginY*/,
+ cWidth, cHeight, cBitsPerPixel);
}
DECLCALLBACK(void) ConsoleVRDPServer::VRDECallbackAudioIn(void *pvCallback,
@@ -1367,8 +1375,14 @@ ConsoleVRDPServer::ConsoleVRDPServer(Console *console)
m_fInterfaceImage = false;
memset(&m_interfaceImage, 0, sizeof (m_interfaceImage));
memset(&m_interfaceCallbacksImage, 0, sizeof (m_interfaceCallbacksImage));
+ RT_ZERO(m_interfaceMousePtr);
RT_ZERO(m_interfaceSCard);
RT_ZERO(m_interfaceCallbacksSCard);
+ RT_ZERO(m_interfaceTSMF);
+ RT_ZERO(m_interfaceCallbacksTSMF);
+
+ rc = RTCritSectInit(&mTSMFLock);
+ AssertRC(rc);
}
ConsoleVRDPServer::~ConsoleVRDPServer()
@@ -1398,6 +1412,12 @@ ConsoleVRDPServer::~ConsoleVRDPServer()
RTCritSectDelete(&mCritSect);
memset(&mCritSect, 0, sizeof(mCritSect));
}
+
+ if (RTCritSectIsInitialized(&mTSMFLock))
+ {
+ RTCritSectDelete(&mTSMFLock);
+ memset(&mTSMFLock, 0, sizeof(mTSMFLock));
+ }
}
int ConsoleVRDPServer::Launch(void)
@@ -1576,9 +1596,28 @@ int ConsoleVRDPServer::Launch(void)
this);
if (RT_SUCCESS(vrc))
{
+ LogRel(("VRDE: [%s]\n", VRDE_IMAGE_INTERFACE_NAME));
m_fInterfaceImage = true;
}
+ /* Mouse pointer interface. */
+ m_interfaceMousePtr.header.u64Version = 1;
+ m_interfaceMousePtr.header.u64Size = sizeof(m_interfaceMousePtr);
+
+ vrc = mpEntryPoints->VRDEGetInterface(mhServer,
+ VRDE_MOUSEPTR_INTERFACE_NAME,
+ &m_interfaceMousePtr.header,
+ NULL,
+ this);
+ if (RT_SUCCESS(vrc))
+ {
+ LogRel(("VRDE: [%s]\n", VRDE_MOUSEPTR_INTERFACE_NAME));
+ }
+ else
+ {
+ RT_ZERO(m_interfaceMousePtr);
+ }
+
/* Smartcard interface. */
m_interfaceSCard.header.u64Version = 1;
m_interfaceSCard.header.u64Size = sizeof(m_interfaceSCard);
@@ -1602,6 +1641,28 @@ int ConsoleVRDPServer::Launch(void)
RT_ZERO(m_interfaceSCard);
}
+ /* Raw TSMF interface. */
+ m_interfaceTSMF.header.u64Version = 1;
+ m_interfaceTSMF.header.u64Size = sizeof(m_interfaceTSMF);
+
+ m_interfaceCallbacksTSMF.header.u64Version = 1;
+ m_interfaceCallbacksTSMF.header.u64Size = sizeof(m_interfaceCallbacksTSMF);
+ m_interfaceCallbacksTSMF.VRDETSMFCbNotify = VRDETSMFCbNotify;
+
+ vrc = mpEntryPoints->VRDEGetInterface(mhServer,
+ VRDE_TSMF_INTERFACE_NAME,
+ &m_interfaceTSMF.header,
+ &m_interfaceCallbacksTSMF.header,
+ this);
+ if (RT_SUCCESS(vrc))
+ {
+ LogRel(("VRDE: [%s]\n", VRDE_TSMF_INTERFACE_NAME));
+ }
+ else
+ {
+ RT_ZERO(m_interfaceTSMF);
+ }
+
/* Since these interfaces are optional, it is always a success here. */
vrc = VINF_SUCCESS;
}
@@ -1745,6 +1806,22 @@ typedef struct H3DORInstance
NULL,
0,
&fu32CompletionFlags);
+ if (RT_FAILURE(rc))
+ {
+ /* No support for a 3D + WINDOW. Try bitmap updates. */
+ fu32CompletionFlags = 0;
+ rc = p->pThis->m_interfaceImage.VRDEImageHandleCreate(p->pThis->mhServer,
+ &p->hImageBitmap,
+ p,
+ u32ScreenId,
+ 0,
+ &rect,
+ VRDE_IMAGE_FMT_ID_BITMAP_BGRA8,
+ NULL,
+ 0,
+ &fu32CompletionFlags);
+ }
+
if (RT_SUCCESS(rc))
{
p->x = x;
@@ -2030,6 +2107,440 @@ int ConsoleVRDPServer::SCardRequest(void *pvUser, uint32_t u32Function, const vo
return rc;
}
+
+struct TSMFHOSTCHCTX;
+struct TSMFVRDPCTX;
+
+typedef struct TSMFHOSTCHCTX
+{
+ ConsoleVRDPServer *pThis;
+
+ struct TSMFVRDPCTX *pVRDPCtx; /* NULL if no corresponding host channel context. */
+
+ void *pvDataReceived;
+ uint32_t cbDataReceived;
+ uint32_t cbDataAllocated;
+} TSMFHOSTCHCTX;
+
+typedef struct TSMFVRDPCTX
+{
+ ConsoleVRDPServer *pThis;
+
+ VBOXHOSTCHANNELCALLBACKS *pCallbacks;
+ void *pvCallbacks;
+
+ TSMFHOSTCHCTX *pHostChCtx; /* NULL if no corresponding host channel context. */
+
+ uint32_t u32ChannelHandle;
+} TSMFVRDPCTX;
+
+static int tsmfContextsAlloc(TSMFHOSTCHCTX **ppHostChCtx, TSMFVRDPCTX **ppVRDPCtx)
+{
+ TSMFHOSTCHCTX *pHostChCtx = (TSMFHOSTCHCTX *)RTMemAllocZ(sizeof(TSMFHOSTCHCTX));
+ if (!pHostChCtx)
+ {
+ return VERR_NO_MEMORY;
+ }
+
+ TSMFVRDPCTX *pVRDPCtx = (TSMFVRDPCTX *)RTMemAllocZ(sizeof(TSMFVRDPCTX));
+ if (!pVRDPCtx)
+ {
+ RTMemFree(pHostChCtx);
+ return VERR_NO_MEMORY;
+ }
+
+ *ppHostChCtx = pHostChCtx;
+ *ppVRDPCtx = pVRDPCtx;
+ return VINF_SUCCESS;
+}
+
+int ConsoleVRDPServer::tsmfLock(void)
+{
+ int rc = RTCritSectEnter(&mTSMFLock);
+ AssertRC(rc);
+ return rc;
+}
+
+void ConsoleVRDPServer::tsmfUnlock(void)
+{
+ RTCritSectLeave(&mTSMFLock);
+}
+
+/* static */ DECLCALLBACK(int) ConsoleVRDPServer::tsmfHostChannelAttach(void *pvProvider,
+ void **ppvChannel,
+ uint32_t u32Flags,
+ VBOXHOSTCHANNELCALLBACKS *pCallbacks,
+ void *pvCallbacks)
+{
+ LogFlowFunc(("\n"));
+
+ ConsoleVRDPServer *pThis = static_cast<ConsoleVRDPServer*>(pvProvider);
+
+ /* Create 2 context structures: for the VRDP server and for the host service. */
+ TSMFHOSTCHCTX *pHostChCtx = NULL;
+ TSMFVRDPCTX *pVRDPCtx = NULL;
+
+ int rc = tsmfContextsAlloc(&pHostChCtx, &pVRDPCtx);
+ if (RT_FAILURE(rc))
+ {
+ return rc;
+ }
+
+ pHostChCtx->pThis = pThis;
+ pHostChCtx->pVRDPCtx = pVRDPCtx;
+
+ pVRDPCtx->pThis = pThis;
+ pVRDPCtx->pCallbacks = pCallbacks;
+ pVRDPCtx->pvCallbacks = pvCallbacks;
+ pVRDPCtx->pHostChCtx = pHostChCtx;
+
+ rc = pThis->m_interfaceTSMF.VRDETSMFChannelCreate(pThis->mhServer, pVRDPCtx, u32Flags);
+
+ if (RT_SUCCESS(rc))
+ {
+ /* @todo contexts should be in a list for accounting. */
+ *ppvChannel = pHostChCtx;
+ }
+ else
+ {
+ RTMemFree(pHostChCtx);
+ RTMemFree(pVRDPCtx);
+ }
+
+ return rc;
+}
+
+/* static */ DECLCALLBACK(void) ConsoleVRDPServer::tsmfHostChannelDetach(void *pvChannel)
+{
+ LogFlowFunc(("\n"));
+
+ TSMFHOSTCHCTX *pHostChCtx = (TSMFHOSTCHCTX *)pvChannel;
+ ConsoleVRDPServer *pThis = pHostChCtx->pThis;
+
+ int rc = pThis->tsmfLock();
+ if (RT_SUCCESS(rc))
+ {
+ bool fClose = false;
+ uint32_t u32ChannelHandle = 0;
+
+ if (pHostChCtx->pVRDPCtx)
+ {
+ /* There is still a VRDP context for this channel. */
+ pHostChCtx->pVRDPCtx->pHostChCtx = NULL;
+ u32ChannelHandle = pHostChCtx->pVRDPCtx->u32ChannelHandle;
+ fClose = true;
+ }
+
+ pThis->tsmfUnlock();
+
+ RTMemFree(pHostChCtx);
+
+ if (fClose)
+ {
+ LogFlowFunc(("Closing VRDE channel %d.\n", u32ChannelHandle));
+ pThis->m_interfaceTSMF.VRDETSMFChannelClose(pThis->mhServer, u32ChannelHandle);
+ }
+ else
+ {
+ LogFlowFunc(("No VRDE channel.\n"));
+ }
+ }
+}
+
+/* static */ DECLCALLBACK(int) ConsoleVRDPServer::tsmfHostChannelSend(void *pvChannel,
+ const void *pvData,
+ uint32_t cbData)
+{
+ LogFlowFunc(("cbData %d\n", cbData));
+
+ TSMFHOSTCHCTX *pHostChCtx = (TSMFHOSTCHCTX *)pvChannel;
+ ConsoleVRDPServer *pThis = pHostChCtx->pThis;
+
+ int rc = pThis->tsmfLock();
+ if (RT_SUCCESS(rc))
+ {
+ bool fSend = false;
+ uint32_t u32ChannelHandle = 0;
+
+ if (pHostChCtx->pVRDPCtx)
+ {
+ u32ChannelHandle = pHostChCtx->pVRDPCtx->u32ChannelHandle;
+ fSend = true;
+ }
+
+ pThis->tsmfUnlock();
+
+ if (fSend)
+ {
+ LogFlowFunc(("Send to VRDE channel %d.\n", u32ChannelHandle));
+ rc = pThis->m_interfaceTSMF.VRDETSMFChannelSend(pThis->mhServer, u32ChannelHandle,
+ pvData, cbData);
+ }
+ }
+
+ return rc;
+}
+
+/* static */ DECLCALLBACK(int) ConsoleVRDPServer::tsmfHostChannelRecv(void *pvChannel,
+ void *pvData,
+ uint32_t cbData,
+ uint32_t *pcbReceived,
+ uint32_t *pcbRemaining)
+{
+ LogFlowFunc(("cbData %d\n", cbData));
+
+ TSMFHOSTCHCTX *pHostChCtx = (TSMFHOSTCHCTX *)pvChannel;
+ ConsoleVRDPServer *pThis = pHostChCtx->pThis;
+
+ int rc = pThis->tsmfLock();
+ if (RT_SUCCESS(rc))
+ {
+ uint32_t cbToCopy = RT_MIN(cbData, pHostChCtx->cbDataReceived);
+ uint32_t cbRemaining = pHostChCtx->cbDataReceived - cbToCopy;
+
+ LogFlowFunc(("cbToCopy %d, cbRemaining %d\n", cbToCopy, cbRemaining));
+
+ if (cbToCopy != 0)
+ {
+ memcpy(pvData, pHostChCtx->pvDataReceived, cbToCopy);
+
+ if (cbRemaining != 0)
+ {
+ memmove(pHostChCtx->pvDataReceived, (uint8_t *)pHostChCtx->pvDataReceived + cbToCopy, cbRemaining);
+ }
+
+ pHostChCtx->cbDataReceived = cbRemaining;
+ }
+
+ pThis->tsmfUnlock();
+
+ *pcbRemaining = cbRemaining;
+ *pcbReceived = cbToCopy;
+ }
+
+ return rc;
+}
+
+/* static */ DECLCALLBACK(int) ConsoleVRDPServer::tsmfHostChannelControl(void *pvChannel,
+ uint32_t u32Code,
+ const void *pvParm,
+ uint32_t cbParm,
+ const void *pvData,
+ uint32_t cbData,
+ uint32_t *pcbDataReturned)
+{
+ LogFlowFunc(("u32Code %u\n", u32Code));
+
+ if (!pvChannel)
+ {
+ /* Special case, the provider must answer rather than a channel instance. */
+ if (u32Code == VBOX_HOST_CHANNEL_CTRL_EXISTS)
+ {
+ *pcbDataReturned = 0;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_NOT_IMPLEMENTED;
+ }
+
+ /* Channels do not support this. */
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+void ConsoleVRDPServer::setupTSMF(void)
+{
+ if (m_interfaceTSMF.header.u64Size == 0)
+ {
+ return;
+ }
+
+ /* Register with the host channel service. */
+ VBOXHOSTCHANNELINTERFACE hostChannelInterface =
+ {
+ this,
+ tsmfHostChannelAttach,
+ tsmfHostChannelDetach,
+ tsmfHostChannelSend,
+ tsmfHostChannelRecv,
+ tsmfHostChannelControl
+ };
+
+ VBoxHostChannelHostRegister parms;
+
+ static char szProviderName[] = "/vrde/tsmf";
+
+ parms.name.type = VBOX_HGCM_SVC_PARM_PTR;
+ parms.name.u.pointer.addr = &szProviderName[0];
+ parms.name.u.pointer.size = sizeof(szProviderName);
+
+ parms.iface.type = VBOX_HGCM_SVC_PARM_PTR;
+ parms.iface.u.pointer.addr = &hostChannelInterface;
+ parms.iface.u.pointer.size = sizeof(hostChannelInterface);
+
+ VMMDev *pVMMDev = mConsole->getVMMDev();
+
+ if (!pVMMDev)
+ {
+ AssertMsgFailed(("setupTSMF no vmmdev\n"));
+ return;
+ }
+
+ int rc = pVMMDev->hgcmHostCall("VBoxHostChannel",
+ VBOX_HOST_CHANNEL_HOST_FN_REGISTER,
+ 2,
+ &parms.name);
+
+ if (!RT_SUCCESS(rc))
+ {
+ Log(("VBOX_HOST_CHANNEL_HOST_FN_REGISTER failed with %Rrc\n", rc));
+ return;
+ }
+
+ LogRel(("VRDE: Enabled TSMF channel.\n"));
+
+ return;
+}
+
+/* @todo these defines must be in a header, which is used by guest component as well. */
+#define VBOX_TSMF_HCH_CREATE_ACCEPTED (VBOX_HOST_CHANNEL_EVENT_USER + 0)
+#define VBOX_TSMF_HCH_CREATE_DECLINED (VBOX_HOST_CHANNEL_EVENT_USER + 1)
+#define VBOX_TSMF_HCH_DISCONNECTED (VBOX_HOST_CHANNEL_EVENT_USER + 2)
+
+/* static */ DECLCALLBACK(void) ConsoleVRDPServer::VRDETSMFCbNotify(void *pvContext,
+ uint32_t u32Notification,
+ void *pvChannel,
+ const void *pvParm,
+ uint32_t cbParm)
+{
+ int rc = VINF_SUCCESS;
+
+ ConsoleVRDPServer *pThis = static_cast<ConsoleVRDPServer*>(pvContext);
+
+ TSMFVRDPCTX *pVRDPCtx = (TSMFVRDPCTX *)pvChannel;
+
+ Assert(pVRDPCtx->pThis == pThis);
+
+ if (pVRDPCtx->pCallbacks == NULL)
+ {
+ LogFlowFunc(("tsmfHostChannel: Channel disconnected. Skipping.\n"));
+ return;
+ }
+
+ switch (u32Notification)
+ {
+ case VRDE_TSMF_N_CREATE_ACCEPTED:
+ {
+ VRDETSMFNOTIFYCREATEACCEPTED *p = (VRDETSMFNOTIFYCREATEACCEPTED *)pvParm;
+ Assert(cbParm == sizeof(VRDETSMFNOTIFYCREATEACCEPTED));
+
+ LogFlowFunc(("tsmfHostChannel: VRDE_TSMF_N_CREATE_ACCEPTED(%p): p->u32ChannelHandle %d\n",
+ pVRDPCtx, p->u32ChannelHandle));
+
+ pVRDPCtx->u32ChannelHandle = p->u32ChannelHandle;
+
+ pVRDPCtx->pCallbacks->HostChannelCallbackEvent(pVRDPCtx->pvCallbacks, pVRDPCtx->pHostChCtx,
+ VBOX_TSMF_HCH_CREATE_ACCEPTED,
+ NULL, 0);
+ } break;
+
+ case VRDE_TSMF_N_CREATE_DECLINED:
+ {
+ LogFlowFunc(("tsmfHostChannel: VRDE_TSMF_N_CREATE_DECLINED(%p)\n", pVRDPCtx));
+
+ pVRDPCtx->pCallbacks->HostChannelCallbackEvent(pVRDPCtx->pvCallbacks, pVRDPCtx->pHostChCtx,
+ VBOX_TSMF_HCH_CREATE_DECLINED,
+ NULL, 0);
+ } break;
+
+ case VRDE_TSMF_N_DATA:
+ {
+ /* Save the data in the intermediate buffer and send the event. */
+ VRDETSMFNOTIFYDATA *p = (VRDETSMFNOTIFYDATA *)pvParm;
+ Assert(cbParm == sizeof(VRDETSMFNOTIFYDATA));
+
+ LogFlowFunc(("tsmfHostChannel: VRDE_TSMF_N_DATA(%p): p->cbData %d\n", pVRDPCtx, p->cbData));
+
+ VBOXHOSTCHANNELEVENTRECV ev;
+ ev.u32SizeAvailable = 0;
+
+ rc = pThis->tsmfLock();
+
+ if (RT_SUCCESS(rc))
+ {
+ TSMFHOSTCHCTX *pHostChCtx = pVRDPCtx->pHostChCtx;
+
+ if (pHostChCtx)
+ {
+ if (pHostChCtx->pvDataReceived)
+ {
+ uint32_t cbAlloc = p->cbData + pHostChCtx->cbDataReceived;
+ pHostChCtx->pvDataReceived = RTMemRealloc(pHostChCtx->pvDataReceived, cbAlloc);
+ memcpy((uint8_t *)pHostChCtx->pvDataReceived + pHostChCtx->cbDataReceived, p->pvData, p->cbData);
+
+ pHostChCtx->cbDataReceived += p->cbData;
+ pHostChCtx->cbDataAllocated = cbAlloc;
+ }
+ else
+ {
+ pHostChCtx->pvDataReceived = RTMemAlloc(p->cbData);
+ memcpy(pHostChCtx->pvDataReceived, p->pvData, p->cbData);
+
+ pHostChCtx->cbDataReceived = p->cbData;
+ pHostChCtx->cbDataAllocated = p->cbData;
+ }
+
+ ev.u32SizeAvailable = p->cbData;
+ }
+ else
+ {
+ LogFlowFunc(("tsmfHostChannel: VRDE_TSMF_N_DATA: no host channel. Skipping\n"));
+ }
+
+ pThis->tsmfUnlock();
+ }
+
+ pVRDPCtx->pCallbacks->HostChannelCallbackEvent(pVRDPCtx->pvCallbacks, pVRDPCtx->pHostChCtx,
+ VBOX_HOST_CHANNEL_EVENT_RECV,
+ &ev, sizeof(ev));
+ } break;
+
+ case VRDE_TSMF_N_DISCONNECTED:
+ {
+ LogFlowFunc(("tsmfHostChannel: VRDE_TSMF_N_DISCONNECTED(%p)\n", pVRDPCtx));
+
+ pVRDPCtx->pCallbacks->HostChannelCallbackEvent(pVRDPCtx->pvCallbacks, pVRDPCtx->pHostChCtx,
+ VBOX_TSMF_HCH_DISCONNECTED,
+ NULL, 0);
+
+ /* The callback context will not be used anymore. */
+ pVRDPCtx->pCallbacks->HostChannelCallbackDeleted(pVRDPCtx->pvCallbacks, pVRDPCtx->pHostChCtx);
+ pVRDPCtx->pCallbacks = NULL;
+ pVRDPCtx->pvCallbacks = NULL;
+
+ rc = pThis->tsmfLock();
+ if (RT_SUCCESS(rc))
+ {
+ if (pVRDPCtx->pHostChCtx)
+ {
+ /* There is still a host channel context for this channel. */
+ pVRDPCtx->pHostChCtx->pVRDPCtx = NULL;
+ }
+
+ pThis->tsmfUnlock();
+
+ memset(pVRDPCtx, 0, sizeof(*pVRDPCtx));
+ RTMemFree(pVRDPCtx);
+ }
+ } break;
+
+ default:
+ {
+ AssertFailed();
+ } break;
+ }
+}
+
void ConsoleVRDPServer::EnableConnections(void)
{
if (mpEntryPoints && mhServer)
@@ -2038,6 +2549,9 @@ void ConsoleVRDPServer::EnableConnections(void)
/* Redirect 3D output if it is enabled. */
remote3DRedirect();
+
+ /* Setup the generic TSMF channel. */
+ setupTSMF();
}
}
@@ -2049,6 +2563,63 @@ void ConsoleVRDPServer::DisconnectClient(uint32_t u32ClientId, bool fReconnect)
}
}
+int ConsoleVRDPServer::MousePointer(BOOL alpha,
+ ULONG xHot,
+ ULONG yHot,
+ ULONG width,
+ ULONG height,
+ const uint8_t *pu8Shape)
+{
+ int rc = VINF_SUCCESS;
+
+ if (mhServer && mpEntryPoints && m_interfaceMousePtr.VRDEMousePtr)
+ {
+ size_t cbMask = (((width + 7) / 8) * height + 3) & ~3;
+ size_t cbData = width * height * 4;
+
+ size_t cbDstMask = alpha? 0: cbMask;
+
+ size_t cbPointer = sizeof(VRDEMOUSEPTRDATA) + cbDstMask + cbData;
+ uint8_t *pu8Pointer = (uint8_t *)RTMemAlloc(cbPointer);
+ if (pu8Pointer != NULL)
+ {
+ VRDEMOUSEPTRDATA *pPointer = (VRDEMOUSEPTRDATA *)pu8Pointer;
+
+ pPointer->u16HotX = (uint16_t)xHot;
+ pPointer->u16HotY = (uint16_t)yHot;
+ pPointer->u16Width = (uint16_t)width;
+ pPointer->u16Height = (uint16_t)height;
+ pPointer->u16MaskLen = (uint16_t)cbDstMask;
+ pPointer->u32DataLen = (uint32_t)cbData;
+
+ /* AND mask. */
+ uint8_t *pu8Mask = pu8Pointer + sizeof(VRDEMOUSEPTRDATA);
+ if (cbDstMask)
+ {
+ memcpy(pu8Mask, pu8Shape, cbDstMask);
+ }
+
+ /* XOR mask */
+ uint8_t *pu8Data = pu8Mask + pPointer->u16MaskLen;
+ memcpy(pu8Data, pu8Shape + cbMask, cbData);
+
+ m_interfaceMousePtr.VRDEMousePtr(mhServer, pPointer);
+
+ RTMemFree(pu8Pointer);
+ }
+ else
+ {
+ rc = VERR_NO_MEMORY;
+ }
+ }
+ else
+ {
+ rc = VERR_NOT_SUPPORTED;
+ }
+
+ return rc;
+}
+
void ConsoleVRDPServer::MousePointerUpdate(const VRDECOLORPOINTER *pPointer)
{
if (mpEntryPoints && mhServer)
diff --git a/src/VBox/Main/src-client/DisplayImpl.cpp b/src/VBox/Main/src-client/DisplayImpl.cpp
index e395a705b..fc2610194 100644
--- a/src/VBox/Main/src-client/DisplayImpl.cpp
+++ b/src/VBox/Main/src-client/DisplayImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -47,6 +47,10 @@
#include <VBox/com/array.h>
+#ifdef VBOX_WITH_VPX
+# include "VideoRec.h"
+#endif
+
/**
* Display driver instance data.
*
@@ -167,7 +171,7 @@ static int displayMakeThumbnail(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
cxThumbnail = (kMaxSizeThumbnail * cx) / cy;
}
- LogFlowFunc(("%dx%d -> %dx%d\n", cx, cy, cxThumbnail, cyThumbnail));
+ LogRelFlowFunc(("%dx%d -> %dx%d\n", cx, cy, cxThumbnail, cyThumbnail));
cbThumbnail = cxThumbnail * 4 * cyThumbnail;
pu8Thumbnail = (uint8_t *)RTMemAlloc(cbThumbnail);
@@ -240,10 +244,21 @@ Display::displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser)
/* Prepare a small thumbnail and a PNG screenshot. */
displayMakeThumbnail(pu8Data, cx, cy, &pu8Thumbnail, &cbThumbnail, &cxThumbnail, &cyThumbnail);
- DisplayMakePNG(pu8Data, cx, cy, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 1);
+ rc = DisplayMakePNG(pu8Data, cx, cy, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 1);
+ if (RT_FAILURE(rc))
+ {
+ if (pu8PNG)
+ {
+ RTMemFree(pu8PNG);
+ pu8PNG = NULL;
+ }
+ cbPNG = 0;
+ cxPNG = 0;
+ cyPNG = 0;
+ }
/* This can be called from any thread. */
- that->mpDrv->pUpPort->pfnFreeScreenshot (that->mpDrv->pUpPort, pu8Data);
+ that->mpDrv->pUpPort->pfnFreeScreenshot(that->mpDrv->pUpPort, pu8Data);
}
}
else
@@ -318,7 +333,7 @@ Display::displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersi
rc = SSMR3GetU32(pSSM, &typeOfBlock);
AssertRCBreak(rc);
- LogFlowFunc(("[%d] type %d, size %d bytes\n", i, typeOfBlock, cbBlock));
+ LogRelFlowFunc(("[%d] type %d, size %d bytes\n", i, typeOfBlock, cbBlock));
/* Note: displaySSMSaveScreenshot writes size of a block = 8 and
* do not write any data if the image size was 0.
@@ -398,6 +413,7 @@ Display::displaySSMLoad(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32
that->maFramebuffers[i].xOrigin = xOrigin;
that->maFramebuffers[i].yOrigin = yOrigin;
that->maFramebuffers[i].flags = (uint16_t)flags;
+ that->maFramebuffers[i].fDisabled = (that->maFramebuffers[i].flags & VBVA_SCREEN_F_DISABLED) != 0;
}
}
@@ -411,12 +427,9 @@ Display::displaySSMLoad(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32
* @param parent handle of our parent object
* @param qemuConsoleData address of common console data structure
*/
-HRESULT Display::init (Console *aParent)
+HRESULT Display::init(Console *aParent)
{
- LogFlowThisFunc(("aParent=%p\n", aParent));
-
ComAssertRet(aParent, E_INVALIDARG);
-
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
AssertReturn(autoInitSpan.isOk(), E_FAIL);
@@ -429,6 +442,34 @@ HRESULT Display::init (Console *aParent)
ULONG ul;
mParent->machine()->COMGETTER(MonitorCount)(&ul);
+
+#ifdef VBOX_WITH_VPX
+ if (VideoRecContextCreate(&mpVideoRecContext))
+ {
+ LogFlow(("Failed to create Video Recording Context\n"));
+ return E_FAIL;
+ }
+
+ BOOL fEnabled = false;
+ mParent->machine()->COMGETTER(VideoCaptureEnabled)(&fEnabled);
+ if (fEnabled)
+ {
+ ULONG ulVideoCaptureHorzRes;
+ mParent->machine()->COMGETTER(VideoCaptureWidth)(&ulVideoCaptureHorzRes);
+ ULONG ulVideoCaptureVertRes;
+ mParent->machine()->COMGETTER(VideoCaptureHeight)(&ulVideoCaptureVertRes);
+ BSTR strVideoCaptureFile;
+ mParent->machine()->COMGETTER(VideoCaptureFile)(&strVideoCaptureFile);
+ LogFlow(("VidoeRecording VPX enabled\n"));
+ if (VideoRecContextInit(mpVideoRecContext, strVideoCaptureFile,
+ ulVideoCaptureHorzRes, ulVideoCaptureVertRes))
+ {
+ LogFlow(("Failed to initialize video recording context\n"));
+ return E_FAIL;
+ }
+ }
+#endif
+
mcMonitors = ul;
for (ul = 0; ul < mcMonitors; ul++)
@@ -438,7 +479,8 @@ HRESULT Display::init (Console *aParent)
maFramebuffers[ul].u32InformationSize = 0;
maFramebuffers[ul].pFramebuffer = NULL;
- maFramebuffers[ul].fDisabled = false;
+ /* All secondary monitors are disabled at startup. */
+ maFramebuffers[ul].fDisabled = ul > 0;
maFramebuffers[ul].xOrigin = 0;
maFramebuffers[ul].yOrigin = 0;
@@ -446,7 +488,7 @@ HRESULT Display::init (Console *aParent)
maFramebuffers[ul].w = 0;
maFramebuffers[ul].h = 0;
- maFramebuffers[ul].flags = 0;
+ maFramebuffers[ul].flags = maFramebuffers[ul].fDisabled? VBVA_SCREEN_F_DISABLED: 0;
maFramebuffers[ul].u16BitsPerPixel = 0;
maFramebuffers[ul].pu8FramebufferVRAM = NULL;
@@ -489,7 +531,7 @@ HRESULT Display::init (Console *aParent)
*/
void Display::uninit()
{
- LogFlowThisFunc(("\n"));
+ LogRelFlowFunc(("this=%p\n", this));
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan(this);
@@ -515,6 +557,11 @@ void Display::uninit()
mpDrv = NULL;
mpVMMDev = NULL;
mfVMMDevInited = true;
+
+#ifdef VBOX_WITH_VPX
+ if (mpVideoRecContext)
+ VideoRecContextClose(mpVideoRecContext);
+#endif
}
/**
@@ -579,7 +626,7 @@ STDMETHODIMP Display::HandleEvent(IEvent * aEvent)
|| machineState == MachineState_LiveSnapshotting
)
{
- LogFlowFunc(("Machine is running.\n"));
+ LogRelFlowFunc(("Machine is running.\n"));
mfMachineRunning = true;
}
@@ -615,7 +662,7 @@ static int callFramebufferResize (IFramebuffer *pFramebuffer, unsigned uScreenId
if (!finished)
{
- LogFlowFunc (("External framebuffer wants us to wait!\n"));
+ LogRelFlowFunc (("External framebuffer wants us to wait!\n"));
return VINF_VGA_RESIZE_IN_PROGRESS;
}
@@ -732,7 +779,7 @@ int Display::handleDisplayResize (unsigned uScreenId, uint32_t bpp, void *pvVRAM
*/
void Display::handleResizeCompletedEMT (void)
{
- LogFlowFunc(("\n"));
+ LogRelFlowFunc(("\n"));
unsigned uScreenId;
for (uScreenId = 0; uScreenId < mcMonitors; uScreenId++)
@@ -805,7 +852,7 @@ void Display::handleResizeCompletedEMT (void)
if (pFBInfo->fDisabled)
pFBInfo->pFramebuffer->NotifyUpdate(0, 0, pFBInfo->w, pFBInfo->h);
}
- LogFlow(("[%d]: default format %d\n", uScreenId, pFBInfo->fDefaultFormat));
+ LogRelFlow(("[%d]: default format %d\n", uScreenId, pFBInfo->fDefaultFormat));
#ifdef DEBUG_sunlover
if (!stam)
@@ -820,7 +867,7 @@ void Display::handleResizeCompletedEMT (void)
#endif /* DEBUG_sunlover */
/* Inform VRDP server about the change of display parameters. */
- LogFlowFunc (("Calling VRDP\n"));
+ LogRelFlowFunc (("Calling VRDP\n"));
mParent->consoleVRDPServer()->SendResize();
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
@@ -988,7 +1035,7 @@ void Display::getFramebufferDimensions(int32_t *px1, int32_t *py1,
AssertPtrReturnVoid(py1);
AssertPtrReturnVoid(px2);
AssertPtrReturnVoid(py2);
- LogFlowFunc(("\n"));
+ LogRelFlowFunc(("\n"));
if (!mpDrv)
return;
@@ -1297,7 +1344,7 @@ static void vbvaSetMemoryFlagsHGSMI (unsigned uScreenId,
bool fVideoAccelVRDP,
DISPLAYFBINFO *pFBInfo)
{
- LogFlowFunc(("HGSMI[%d]: %p\n", uScreenId, pFBInfo->pVBVAHostFlags));
+ LogRelFlowFunc(("HGSMI[%d]: %p\n", uScreenId, pFBInfo->pVBVAHostFlags));
if (pFBInfo->pVBVAHostFlags)
{
@@ -1316,7 +1363,7 @@ static void vbvaSetMemoryFlagsHGSMI (unsigned uScreenId,
ASMAtomicWriteU32(&pFBInfo->pVBVAHostFlags->u32HostEvents, fu32HostEvents);
ASMAtomicWriteU32(&pFBInfo->pVBVAHostFlags->u32SupportedOrders, fu32SupportedOrders);
- LogFlowFunc((" fu32HostEvents = 0x%08X, fu32SupportedOrders = 0x%08X\n", fu32HostEvents, fu32SupportedOrders));
+ LogRelFlowFunc((" fu32HostEvents = 0x%08X, fu32SupportedOrders = 0x%08X\n", fu32HostEvents, fu32SupportedOrders));
}
}
@@ -1375,7 +1422,7 @@ int Display::videoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
* Guest enabled acceleration at will. And it has to enable
* acceleration after a mode change.
*/
- LogFlowFunc (("mfVideoAccelEnabled = %d, fEnable = %d, pVbvaMemory = %p\n",
+ LogRelFlowFunc (("mfVideoAccelEnabled = %d, fEnable = %d, pVbvaMemory = %p\n",
mfVideoAccelEnabled, fEnable, pVbvaMemory));
/* Strictly check parameters. Callers must not pass anything in the case. */
@@ -1392,7 +1439,7 @@ int Display::videoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
{
Assert (!mfVideoAccelEnabled);
- LogFlowFunc (("Machine is not yet running.\n"));
+ LogRelFlowFunc (("Machine is not yet running.\n"));
if (fEnable)
{
@@ -1460,7 +1507,7 @@ int Display::videoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
LogRel(("VBVA: Disabled.\n"));
}
- LogFlowFunc (("VideoAccelEnable: rc = %Rrc.\n", rc));
+ LogRelFlowFunc (("VideoAccelEnable: rc = %Rrc.\n", rc));
return rc;
}
@@ -1469,7 +1516,7 @@ int Display::videoAccelEnable (bool fEnable, VBVAMEMORY *pVbvaMemory)
*/
void Display::VideoAccelVRDP (bool fEnable)
{
- LogFlowFunc(("fEnable = %d\n", fEnable));
+ LogRelFlowFunc(("fEnable = %d\n", fEnable));
vbvaLock();
@@ -1724,7 +1771,7 @@ bool Display::vbvaFetchCmd (VBVACMDHDR **ppHdr, uint32_t *pcbCmd)
if (!dst)
{
- LogFlowFunc (("could not allocate %d bytes from heap!!!\n", cbRecord));
+ LogRelFlowFunc (("could not allocate %d bytes from heap!!!\n", cbRecord));
mpVbvaMemory->off32Data = (mpVbvaMemory->off32Data + cbRecord) % VBVA_RING_BUFFER_SIZE;
return false;
}
@@ -1979,7 +2026,7 @@ int Display::videoAccelRefreshProcess(void)
STDMETHODIMP Display::GetScreenResolution (ULONG aScreenId,
ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel)
{
- LogFlowFunc (("aScreenId = %d\n", aScreenId));
+ LogRelFlowFunc (("aScreenId = %d\n", aScreenId));
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2024,7 +2071,7 @@ STDMETHODIMP Display::GetScreenResolution (ULONG aScreenId,
STDMETHODIMP Display::SetFramebuffer (ULONG aScreenId,
IFramebuffer *aFramebuffer)
{
- LogFlowFunc (("\n"));
+ LogRelFlowFunc (("\n"));
if (aFramebuffer != NULL)
CheckComArgOutPointerValid(aFramebuffer);
@@ -2037,15 +2084,15 @@ STDMETHODIMP Display::SetFramebuffer (ULONG aScreenId,
Console::SafeVMPtrQuiet pVM (mParent);
if (pVM.isOk())
{
- /* Must leave the lock here because the changeFramebuffer will
+ /* Must release the lock here because the changeFramebuffer will
* also obtain it. */
- alock.leave ();
+ alock.release();
/* send request to the EMT thread */
int vrc = VMR3ReqCallWait (pVM, VMCPUID_ANY,
(PFNRT) changeFramebuffer, 3, this, aFramebuffer, aScreenId);
- alock.enter ();
+ alock.acquire();
ComAssertRCRet (vrc, E_FAIL);
@@ -2063,13 +2110,13 @@ STDMETHODIMP Display::SetFramebuffer (ULONG aScreenId,
VMMDev *pVMMDev = mParent->getVMMDev();
- alock.leave ();
+ alock.release();
if (pVMMDev)
vrc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SCREEN_CHANGED, SHCRGL_CPARMS_SCREEN_CHANGED, &parm);
/*ComAssertRCRet (vrc, E_FAIL);*/
- alock.enter ();
+ alock.acquire();
}
}
#endif /* VBOX_WITH_CROGL */
@@ -2087,7 +2134,7 @@ STDMETHODIMP Display::SetFramebuffer (ULONG aScreenId,
STDMETHODIMP Display::GetFramebuffer (ULONG aScreenId,
IFramebuffer **aFramebuffer, LONG *aXOrigin, LONG *aYOrigin)
{
- LogFlowFunc (("aScreenId = %d\n", aScreenId));
+ LogRelFlowFunc (("aScreenId = %d\n", aScreenId));
CheckComArgOutPointerValid(aFramebuffer);
@@ -2113,8 +2160,9 @@ STDMETHODIMP Display::GetFramebuffer (ULONG aScreenId,
return S_OK;
}
-STDMETHODIMP Display::SetVideoModeHint(ULONG aWidth, ULONG aHeight,
- ULONG aBitsPerPixel, ULONG aDisplay)
+STDMETHODIMP Display::SetVideoModeHint(ULONG aDisplay, BOOL aEnabled,
+ BOOL aChangeOrigin, LONG aOriginX, LONG aOriginY,
+ ULONG aWidth, ULONG aHeight, ULONG aBitsPerPixel)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2123,6 +2171,12 @@ STDMETHODIMP Display::SetVideoModeHint(ULONG aWidth, ULONG aHeight,
CHECK_CONSOLE_DRV (mpDrv);
+ /* XXX Ignore these parameters for now: */
+ NOREF(aChangeOrigin);
+ NOREF(aOriginX);
+ NOREF(aOriginY);
+ NOREF(aEnabled);
+
/*
* Do some rough checks for valid input
*/
@@ -2147,16 +2201,14 @@ STDMETHODIMP Display::SetVideoModeHint(ULONG aWidth, ULONG aHeight,
if (aDisplay >= cMonitors)
return E_INVALIDARG;
-// sunlover 20070614: It is up to the guest to decide whether the hint is valid.
-// ULONG vramSize;
-// mParent->machine()->COMGETTER(VRAMSize)(&vramSize);
-// /* enough VRAM? */
-// if ((width * height * (bpp / 8)) > (vramSize * 1024 * 1024))
-// return setError(E_FAIL, tr("Not enough VRAM for the selected video mode"));
+ /*
+ * sunlover 20070614: It is up to the guest to decide whether the hint is
+ * valid. Therefore don't do any VRAM sanity checks here!
+ */
- /* Have to leave the lock because the pfnRequestDisplayChange
+ /* Have to release the lock because the pfnRequestDisplayChange
* will call EMT. */
- alock.leave ();
+ alock.release();
VMMDev *pVMMDev = mParent->getVMMDev();
if (pVMMDev)
@@ -2175,8 +2227,8 @@ STDMETHODIMP Display::SetSeamlessMode (BOOL enabled)
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Have to leave the lock because the pfnRequestSeamlessChange will call EMT. */
- alock.leave ();
+ /* Have to release the lock because the pfnRequestSeamlessChange will call EMT. */
+ alock.release();
VMMDev *pVMMDev = mParent->getVMMDev();
if (pVMMDev)
@@ -2310,7 +2362,7 @@ static int displayTakeScreenshot(PVM pVM, Display *pDisplay, struct DRVMAINDISPL
else
{
/* Scale. */
- LogFlowFunc(("SCALE: %dx%d -> %dx%d\n", cx, cy, width, height));
+ LogRelFlowFunc(("SCALE: %dx%d -> %dx%d\n", cx, cy, width, height));
uint8_t *dst = address;
uint8_t *src = pu8Data;
@@ -2320,17 +2372,17 @@ static int displayTakeScreenshot(PVM pVM, Display *pDisplay, struct DRVMAINDISPL
int srcH = cy;
int iDeltaLine = cx * 4;
- BitmapScale32 (dst,
- dstW, dstH,
- src,
- iDeltaLine,
- srcW, srcH);
+ BitmapScale32(dst,
+ dstW, dstH,
+ src,
+ iDeltaLine,
+ srcW, srcH);
}
if (aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
{
/* This can be called from any thread. */
- pDrv->pUpPort->pfnFreeScreenshot (pDrv->pUpPort, pu8Data);
+ pDrv->pUpPort->pfnFreeScreenshot(pDrv->pUpPort, pu8Data);
}
else
{
@@ -2341,7 +2393,7 @@ static int displayTakeScreenshot(PVM pVM, Display *pDisplay, struct DRVMAINDISPL
return vrc;
}
-STDMETHODIMP Display::TakeScreenShot (ULONG aScreenId, BYTE *address, ULONG width, ULONG height)
+STDMETHODIMP Display::TakeScreenShot(ULONG aScreenId, BYTE *address, ULONG width, ULONG height)
{
/// @todo (r=dmik) this function may take too long to complete if the VM
// is doing something like saving state right now. Which, in case if it
@@ -2349,9 +2401,8 @@ STDMETHODIMP Display::TakeScreenShot (ULONG aScreenId, BYTE *address, ULONG widt
// check the machine state here (by enclosing the check and VMRequCall
// within the Console lock to make it atomic).
- LogFlowFuncEnter();
- LogFlowFunc (("address=%p, width=%d, height=%d\n",
- address, width, height));
+ LogRelFlowFunc(("address=%p, width=%d, height=%d\n",
+ address, width, height));
CheckComArgNotNull(address);
CheckComArgExpr(width, width != 0);
@@ -2368,21 +2419,21 @@ STDMETHODIMP Display::TakeScreenShot (ULONG aScreenId, BYTE *address, ULONG widt
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- CHECK_CONSOLE_DRV (mpDrv);
+ CHECK_CONSOLE_DRV(mpDrv);
Console::SafeVMPtr pVM(mParent);
if (FAILED(pVM.rc())) return pVM.rc();
HRESULT rc = S_OK;
- LogFlowFunc (("Sending SCREENSHOT request\n"));
+ LogRelFlowFunc(("Sending SCREENSHOT request\n"));
- /* Leave lock because other thread (EMT) is called and it may initiate a resize
+ /* Release lock because other thread (EMT) is called and it may initiate a resize
* which also needs lock.
*
* This method does not need the lock anymore.
*/
- alock.leave();
+ alock.release();
int vrc = displayTakeScreenshot(pVM, this, mpDrv, aScreenId, address, width, height);
@@ -2396,17 +2447,14 @@ STDMETHODIMP Display::TakeScreenShot (ULONG aScreenId, BYTE *address, ULONG widt
rc = setError(VBOX_E_IPRT_ERROR,
tr("Could not take a screenshot (%Rrc)"), vrc);
- LogFlowFunc (("rc=%08X\n", rc));
- LogFlowFuncLeave();
+ LogRelFlowFunc(("rc=%08X\n", rc));
return rc;
}
-STDMETHODIMP Display::TakeScreenShotToArray (ULONG aScreenId, ULONG width, ULONG height,
- ComSafeArrayOut(BYTE, aScreenData))
+STDMETHODIMP Display::TakeScreenShotToArray(ULONG aScreenId, ULONG width, ULONG height,
+ ComSafeArrayOut(BYTE, aScreenData))
{
- LogFlowFuncEnter();
- LogFlowFunc (("width=%d, height=%d\n",
- width, height));
+ LogRelFlowFunc(("width=%d, height=%d\n", width, height));
CheckComArgOutSafeArrayPointerValid(aScreenData);
CheckComArgExpr(width, width != 0);
@@ -2423,21 +2471,21 @@ STDMETHODIMP Display::TakeScreenShotToArray (ULONG aScreenId, ULONG width, ULONG
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- CHECK_CONSOLE_DRV (mpDrv);
+ CHECK_CONSOLE_DRV(mpDrv);
Console::SafeVMPtr pVM(mParent);
if (FAILED(pVM.rc())) return pVM.rc();
HRESULT rc = S_OK;
- LogFlowFunc (("Sending SCREENSHOT request\n"));
+ LogRelFlowFunc(("Sending SCREENSHOT request\n"));
- /* Leave lock because other thread (EMT) is called and it may initiate a resize
+ /* Release lock because other thread (EMT) is called and it may initiate a resize
* which also needs lock.
*
* This method does not need the lock anymore.
*/
- alock.leave();
+ alock.release();
size_t cbData = width * 4 * height;
uint8_t *pu8Data = (uint8_t *)RTMemAlloc(cbData);
@@ -2462,7 +2510,7 @@ STDMETHODIMP Display::TakeScreenShotToArray (ULONG aScreenId, ULONG width, ULONG
pu8 += 4;
}
- com::SafeArray<BYTE> screenData (cbData);
+ com::SafeArray<BYTE> screenData(cbData);
screenData.initFrom(pu8Data, cbData);
screenData.detachTo(ComSafeArrayOutArg(aScreenData));
}
@@ -2475,17 +2523,14 @@ STDMETHODIMP Display::TakeScreenShotToArray (ULONG aScreenId, ULONG width, ULONG
RTMemFree(pu8Data);
- LogFlowFunc (("rc=%08X\n", rc));
- LogFlowFuncLeave();
+ LogRelFlowFunc(("rc=%08X\n", rc));
return rc;
}
-STDMETHODIMP Display::TakeScreenShotPNGToArray (ULONG aScreenId, ULONG width, ULONG height,
- ComSafeArrayOut(BYTE, aScreenData))
+STDMETHODIMP Display::TakeScreenShotPNGToArray(ULONG aScreenId, ULONG width, ULONG height,
+ ComSafeArrayOut(BYTE, aScreenData))
{
- LogFlowFuncEnter();
- LogFlowFunc (("width=%d, height=%d\n",
- width, height));
+ LogRelFlowFunc(("width=%d, height=%d\n", width, height));
CheckComArgOutSafeArrayPointerValid(aScreenData);
CheckComArgExpr(width, width != 0);
@@ -2502,21 +2547,21 @@ STDMETHODIMP Display::TakeScreenShotPNGToArray (ULONG aScreenId, ULONG width, UL
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- CHECK_CONSOLE_DRV (mpDrv);
+ CHECK_CONSOLE_DRV(mpDrv);
Console::SafeVMPtr pVM(mParent);
if (FAILED(pVM.rc())) return pVM.rc();
HRESULT rc = S_OK;
- LogFlowFunc (("Sending SCREENSHOT request\n"));
+ LogRelFlowFunc(("Sending SCREENSHOT request\n"));
- /* Leave lock because other thread (EMT) is called and it may initiate a resize
+ /* Release lock because other thread (EMT) is called and it may initiate a resize
* which also needs lock.
*
* This method does not need the lock anymore.
*/
- alock.leave();
+ alock.release();
size_t cbData = width * 4 * height;
uint8_t *pu8Data = (uint8_t *)RTMemAlloc(cbData);
@@ -2533,13 +2578,23 @@ STDMETHODIMP Display::TakeScreenShotPNGToArray (ULONG aScreenId, ULONG width, UL
uint32_t cxPNG = 0;
uint32_t cyPNG = 0;
- DisplayMakePNG(pu8Data, width, height, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 0);
-
- com::SafeArray<BYTE> screenData (cbPNG);
- screenData.initFrom(pu8PNG, cbPNG);
- RTMemFree(pu8PNG);
+ vrc = DisplayMakePNG(pu8Data, width, height, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 0);
+ if (RT_SUCCESS(vrc))
+ {
+ com::SafeArray<BYTE> screenData(cbPNG);
+ screenData.initFrom(pu8PNG, cbPNG);
+ if (pu8PNG)
+ RTMemFree(pu8PNG);
- screenData.detachTo(ComSafeArrayOutArg(aScreenData));
+ screenData.detachTo(ComSafeArrayOutArg(aScreenData));
+ }
+ else
+ {
+ if (pu8PNG)
+ RTMemFree(pu8PNG);
+ rc = setError(VBOX_E_IPRT_ERROR,
+ tr("Could not convert screenshot to PNG (%Rrc)"), vrc);
+ }
}
else if (vrc == VERR_NOT_IMPLEMENTED)
rc = setError(E_NOTIMPL,
@@ -2550,8 +2605,7 @@ STDMETHODIMP Display::TakeScreenShotPNGToArray (ULONG aScreenId, ULONG width, UL
RTMemFree(pu8Data);
- LogFlowFunc (("rc=%08X\n", rc));
- LogFlowFuncLeave();
+ LogRelFlowFunc(("rc=%08X\n", rc));
return rc;
}
@@ -2651,6 +2705,10 @@ int Display::drawToScreenEMT(Display *pDisplay, ULONG aScreenId, BYTE *address,
{
rc = VERR_INVALID_PARAMETER;
}
+
+ if (RT_SUCCESS(rc) && pDisplay->maFramebuffers[aScreenId].u32ResizeStatus == ResizeStatus_Void)
+ pDisplay->mParent->consoleVRDPServer()->SendUpdateBitmap(aScreenId, x, y, width, height);
+
pDisplay->vbvaUnlock();
return rc;
}
@@ -2664,8 +2722,7 @@ STDMETHODIMP Display::DrawToScreen (ULONG aScreenId, BYTE *address, ULONG x, ULO
// check the machine state here (by enclosing the check and VMRequCall
// within the Console lock to make it atomic).
- LogFlowFuncEnter();
- LogFlowFunc (("address=%p, x=%d, y=%d, width=%d, height=%d\n",
+ LogRelFlowFunc (("address=%p, x=%d, y=%d, width=%d, height=%d\n",
(void *)address, x, y, width, height));
CheckComArgNotNull(address);
@@ -2682,8 +2739,8 @@ STDMETHODIMP Display::DrawToScreen (ULONG aScreenId, BYTE *address, ULONG x, ULO
Console::SafeVMPtr pVM(mParent);
if (FAILED(pVM.rc())) return pVM.rc();
- /* Leave lock because the call scheduled on EMT may also try to take it. */
- alock.leave();
+ /* Release lock because the call scheduled on EMT may also try to take it. */
+ alock.release();
/*
* Again we're lazy and make the graphics device do all the
@@ -2712,8 +2769,7 @@ STDMETHODIMP Display::DrawToScreen (ULONG aScreenId, BYTE *address, ULONG x, ULO
// handleDisplayUpdate (x, y, width, height);
// }
- LogFlowFunc (("rc=%08X\n", rc));
- LogFlowFuncLeave();
+ LogRelFlowFunc (("rc=%08X\n", rc));
return rc;
}
@@ -2791,7 +2847,7 @@ void Display::InvalidateAndUpdateEMT(Display *pDisplay)
*/
STDMETHODIMP Display::InvalidateAndUpdate()
{
- LogFlowFuncEnter();
+ LogRelFlowFunc(("\n"));
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2805,22 +2861,21 @@ STDMETHODIMP Display::InvalidateAndUpdate()
HRESULT rc = S_OK;
- LogFlowFunc (("Sending DPYUPDATE request\n"));
+ LogRelFlowFunc (("Sending DPYUPDATE request\n"));
- /* Have to leave the lock when calling EMT. */
- alock.leave ();
+ /* Have to release the lock when calling EMT. */
+ alock.release();
/* pdm.h says that this has to be called from the EMT thread */
int rcVBox = VMR3ReqCallVoidWait(pVM, VMCPUID_ANY, (PFNRT)Display::InvalidateAndUpdateEMT,
1, this);
- alock.enter ();
+ alock.acquire();
if (RT_FAILURE(rcVBox))
rc = setError(VBOX_E_IPRT_ERROR,
tr("Could not invalidate and update the screen (%Rrc)"), rcVBox);
- LogFlowFunc (("rc=%08X\n", rc));
- LogFlowFuncLeave();
+ LogRelFlowFunc (("rc=%08X\n", rc));
return rc;
}
@@ -2832,7 +2887,7 @@ STDMETHODIMP Display::InvalidateAndUpdate()
*/
STDMETHODIMP Display::ResizeCompleted(ULONG aScreenId)
{
- LogFlowFunc (("\n"));
+ LogRelFlowFunc (("\n"));
/// @todo (dmik) can we AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); here?
// This will require general code review and may add some details.
@@ -2868,6 +2923,41 @@ STDMETHODIMP Display::CompleteVHWACommand(BYTE *pCommand)
#endif
}
+STDMETHODIMP Display::ViewportChanged(ULONG aScreenId, ULONG x, ULONG y, ULONG width, ULONG height)
+{
+#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
+ BOOL is3denabled;
+ mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
+
+ if (is3denabled)
+ {
+ VBOXHGCMSVCPARM aParms[5];
+
+ aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[0].u.uint32 = aScreenId;
+
+ aParms[1].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[1].u.uint32 = x;
+
+ aParms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[2].u.uint32 = y;
+
+
+ aParms[3].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[3].u.uint32 = width;
+
+ aParms[4].type = VBOX_HGCM_SVC_PARM_32BIT;
+ aParms[4].u.uint32 = height;
+
+ VMMDev *pVMMDev = mParent->getVMMDev();
+
+ if (pVMMDev)
+ pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_VIEWPORT_CHANGED, SHCRGL_CPARMS_VIEWPORT_CHANGED, aParms);
+ }
+#endif /* VBOX_WITH_CROGL && VBOX_WITH_HGCM */
+ return S_OK;
+}
+
// private methods
/////////////////////////////////////////////////////////////////////////////
@@ -2878,7 +2968,7 @@ STDMETHODIMP Display::CompleteVHWACommand(BYTE *pCommand)
*/
void Display::updateDisplayData(void)
{
- LogFlowFunc (("\n"));
+ LogRelFlowFunc (("\n"));
/* the driver might not have been constructed yet */
if (!mpDrv)
@@ -2935,7 +3025,7 @@ void Display::updateDisplayData(void)
mpDrv->IConnector.cx = 0;
mpDrv->IConnector.cy = 0;
}
- LogFlowFunc (("leave\n"));
+ LogRelFlowFunc (("leave\n"));
}
#ifdef VBOX_WITH_CRHGSMI
@@ -2989,7 +3079,7 @@ void Display::destructCrHgsmiData(void)
DECLCALLBACK(int) Display::changeFramebuffer (Display *that, IFramebuffer *aFB,
unsigned uScreenId)
{
- LogFlowFunc (("uScreenId = %d\n", uScreenId));
+ LogRelFlowFunc (("uScreenId = %d\n", uScreenId));
AssertReturn(that, VERR_INVALID_PARAMETER);
AssertReturn(uScreenId < that->mcMonitors, VERR_INVALID_PARAMETER);
@@ -3011,14 +3101,14 @@ DECLCALLBACK(int) Display::changeFramebuffer (Display *that, IFramebuffer *aFB,
DISPLAYFBINFO *pFBInfo = &that->maFramebuffers[uScreenId];
#if defined(VBOX_WITH_CROGL)
- /* Leave the lock, because SHCRGL_HOST_FN_SCREEN_CHANGED will read current framebuffer */
+ /* Release the lock, because SHCRGL_HOST_FN_SCREEN_CHANGED will read current framebuffer */
{
BOOL is3denabled;
that->mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
if (is3denabled)
{
- alock.leave ();
+ alock.release();
}
}
#endif
@@ -3047,7 +3137,7 @@ DECLCALLBACK(int) Display::changeFramebuffer (Display *that, IFramebuffer *aFB,
}
}
- LogFlowFunc (("leave\n"));
+ LogRelFlowFunc (("leave\n"));
return VINF_SUCCESS;
}
@@ -3061,7 +3151,7 @@ DECLCALLBACK(int) Display::displayResizeCallback(PPDMIDISPLAYCONNECTOR pInterfac
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- LogFlowFunc (("bpp %d, pvVRAM %p, cbLine %d, cx %d, cy %d\n",
+ LogRelFlowFunc (("bpp %d, pvVRAM %p, cbLine %d, cx %d, cy %d\n",
bpp, pvVRAM, cbLine, cx, cy));
return pDrv->pDisplay->handleDisplayResize(VBOX_VIDEO_PRIMARY_SCREEN, bpp, pvVRAM, cbLine, cx, cy, VBVA_SCREEN_F_ACTIVE);
@@ -3112,6 +3202,7 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
bool fNoUpdate = false; /* Do not update the display if any of the framebuffers is being resized. */
unsigned uScreenId;
+ LogFlow(("DisplayRefreshCallback\n"));
for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++)
{
DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[uScreenId];
@@ -3123,7 +3214,7 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
if (u32ResizeStatus == ResizeStatus_UpdateDisplayData)
{
- LogFlowFunc (("ResizeStatus_UpdateDisplayData %d\n", uScreenId));
+ LogRelFlowFunc (("ResizeStatus_UpdateDisplayData %d\n", uScreenId));
fNoUpdate = true; /* Always set it here, because pfnUpdateDisplayAll can cause a new resize. */
/* The framebuffer was resized and display data need to be updated. */
pDisplay->handleResizeCompletedEMT ();
@@ -3140,7 +3231,7 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
else if (u32ResizeStatus == ResizeStatus_InProgress)
{
/* The framebuffer is being resized. Do not call the VGA device back. Immediately return. */
- LogFlowFunc (("ResizeStatus_InProcess\n"));
+ LogRelFlowFunc (("ResizeStatus_InProcess\n"));
fNoUpdate = true;
continue;
}
@@ -3149,7 +3240,6 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
if (!fNoUpdate)
{
int rc = pDisplay->videoAccelRefreshProcess();
-
if (rc != VINF_TRY_AGAIN) /* Means 'do nothing' here. */
{
if (rc == VWRN_INVALID_STATE)
@@ -3184,6 +3274,68 @@ DECLCALLBACK(void) Display::displayRefreshCallback(PPDMIDISPLAYCONNECTOR pInterf
}
}
+#ifdef VBOX_WITH_VPX
+ if (VideoRecIsEnabled(pDisplay->mpVideoRecContext))
+ {
+ uint32_t u32VideoRecImgFormat = VPX_IMG_FMT_NONE;
+ ULONG ulGuestHeight = 0;
+ ULONG ulGuestWidth = 0;
+ ULONG ulBitsPerPixel;
+ int rc;
+ DISPLAYFBINFO *pFBInfo = &pDisplay->maFramebuffers[VBOX_VIDEO_PRIMARY_SCREEN];
+
+ if ( !pFBInfo->pFramebuffer.isNull()
+ && !(pFBInfo->fDisabled)
+ && pFBInfo->u32ResizeStatus == ResizeStatus_Void)
+ {
+ if (pFBInfo->fVBVAEnabled && pFBInfo->pu8FramebufferVRAM)
+ {
+ rc = VideoRecCopyToIntBuffer(pDisplay->mpVideoRecContext, 0, 0,
+ FramebufferPixelFormat_FOURCC_RGB, pFBInfo->u16BitsPerPixel,
+ pFBInfo->u32LineSize, pFBInfo->w, pFBInfo->h,
+ pFBInfo->pu8FramebufferVRAM);
+ ulGuestWidth = pFBInfo->w;
+ ulGuestHeight = pFBInfo->h;
+ ulBitsPerPixel = pFBInfo->u16BitsPerPixel;
+ }
+ else
+ {
+ rc = VideoRecCopyToIntBuffer(pDisplay->mpVideoRecContext, 0, 0,
+ FramebufferPixelFormat_FOURCC_RGB, pDrv->IConnector.cBits,
+ pDrv->IConnector.cbScanline, pDrv->IConnector.cx,
+ pDrv->IConnector.cy, pDrv->IConnector.pu8Data);
+ ulGuestWidth = pDrv->IConnector.cx;
+ ulGuestHeight = pDrv->IConnector.cy;
+ ulBitsPerPixel = pDrv->IConnector.cBits;
+ }
+
+ switch (ulBitsPerPixel)
+ {
+ case 32:
+ u32VideoRecImgFormat = VPX_IMG_FMT_RGB32;
+ Log2(("FFmpeg::RequestResize: setting ffmpeg pixel format to VPX_IMG_FMT_RGB32\n"));
+ break;
+ case 24:
+ u32VideoRecImgFormat = VPX_IMG_FMT_RGB24;
+ Log2(("FFmpeg::RequestResize: setting ffmpeg pixel format to VPX_IMG_FMT_RGB24\n"));
+ break;
+ case 16:
+ u32VideoRecImgFormat = VPX_IMG_FMT_RGB565;
+ Log2(("FFmpeg::RequestResize: setting ffmpeg pixel format to VPX_IMG_FMT_RGB565\n"));
+ break;
+ default:
+ Log2(("No Proper Format detected\n"));
+ break;
+ }
+
+ /* Just return in case of failure without any assertion */
+ if( RT_SUCCESS(rc))
+ if (RT_SUCCESS(VideoRecDoRGBToYUV(pDisplay->mpVideoRecContext, u32VideoRecImgFormat)))
+ VideoRecEncodeAndWrite(pDisplay->mpVideoRecContext, ulGuestWidth, ulGuestHeight);
+ }
+ }
+#endif
+
#ifdef DEBUG_sunlover
STAM_PROFILE_STOP(&StatDisplayRefresh, a);
#endif /* DEBUG_sunlover */
@@ -3201,9 +3353,9 @@ DECLCALLBACK(void) Display::displayResetCallback(PPDMIDISPLAYCONNECTOR pInterfac
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- LogFlowFunc (("\n"));
+ LogRelFlowFunc (("\n"));
- /* Disable VBVA mode. */
+ /* Disable VBVA mode. */
pDrv->pDisplay->VideoAccelEnable (false, NULL);
}
@@ -3216,7 +3368,7 @@ DECLCALLBACK(void) Display::displayLFBModeChangeCallback(PPDMIDISPLAYCONNECTOR p
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
- LogFlowFunc (("fEnabled=%d\n", fEnabled));
+ LogRelFlowFunc (("fEnabled=%d\n", fEnabled));
NOREF(fEnabled);
@@ -3290,7 +3442,7 @@ DECLCALLBACK(void) Display::displayProcessAdapterDataCallback(PPDMIDISPLAYCONNEC
pFBInfo->u32MaxFramebufferSize = pDisplay->u32FramebufferSize;
pFBInfo->u32InformationSize = pDisplay->u32InformationSize;
- LogFlow(("VBOX_VIDEO_INFO_TYPE_DISPLAY: %d: at 0x%08X, size 0x%08X, info 0x%08X\n", pDisplay->u32Index, pDisplay->u32Offset, pDisplay->u32FramebufferSize, pDisplay->u32InformationSize));
+ LogRelFlow(("VBOX_VIDEO_INFO_TYPE_DISPLAY: %d: at 0x%08X, size 0x%08X, info 0x%08X\n", pDisplay->u32Index, pDisplay->u32Offset, pDisplay->u32FramebufferSize, pDisplay->u32InformationSize));
}
else if (pHdr->u8Type == VBOX_VIDEO_INFO_TYPE_QUERY_CONF32)
{
@@ -3393,12 +3545,22 @@ DECLCALLBACK(void) Display::displayProcessDisplayDataCallback(PPDMIDISPLAYCONNEC
pFBInfo->w = pScreen->u16Width;
pFBInfo->h = pScreen->u16Height;
- LogFlow(("VBOX_VIDEO_INFO_TYPE_SCREEN: (%p) %d: at %d,%d, linesize 0x%X, size %dx%d, bpp %d, flags 0x%02X\n",
+ LogRelFlow(("VBOX_VIDEO_INFO_TYPE_SCREEN: (%p) %d: at %d,%d, linesize 0x%X, size %dx%d, bpp %d, flags 0x%02X\n",
pHdr, uScreenId, pScreen->xOrigin, pScreen->yOrigin, pScreen->u32LineSize, pScreen->u16Width, pScreen->u16Height, pScreen->bitsPerPixel, pScreen->u8Flags));
if (uScreenId != VBOX_VIDEO_PRIMARY_SCREEN)
{
- /* Primary screen resize is initiated by the VGA device. */
+ /* Primary screen resize is eeeeeeeee by the VGA device. */
+ if (pFBInfo->fDisabled)
+ {
+ pFBInfo->fDisabled = false;
+ fireGuestMonitorChangedEvent(pDrv->pDisplay->mParent->getEventSource(),
+ GuestMonitorChangedEventType_Enabled,
+ uScreenId,
+ pFBInfo->xOrigin, pFBInfo->yOrigin,
+ pFBInfo->w, pFBInfo->h);
+ }
+
pDrv->pDisplay->handleDisplayResize(uScreenId, pScreen->bitsPerPixel, (uint8_t *)pvVRAM + pFBInfo->u32Offset, pScreen->u32LineSize, pScreen->u16Width, pScreen->u16Height, VBVA_SCREEN_F_ACTIVE);
}
}
@@ -3592,7 +3754,7 @@ DECLCALLBACK(void) Display::displayCrHgsmiControlCompletion(int32_t result, uint
#ifdef VBOX_WITH_HGSMI
DECLCALLBACK(int) Display::displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags)
{
- LogFlowFunc(("uScreenId %d\n", uScreenId));
+ LogRelFlowFunc(("uScreenId %d\n", uScreenId));
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
Display *pThis = pDrv->pDisplay;
@@ -3607,13 +3769,29 @@ DECLCALLBACK(int) Display::displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, u
DECLCALLBACK(void) Display::displayVBVADisable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId)
{
- LogFlowFunc(("uScreenId %d\n", uScreenId));
+ LogRelFlowFunc(("uScreenId %d\n", uScreenId));
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
Display *pThis = pDrv->pDisplay;
DISPLAYFBINFO *pFBInfo = &pThis->maFramebuffers[uScreenId];
+ if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)
+ {
+ /* Make sure that the primary screen is visible now.
+ * The guest can't use VBVA anymore, so only only the VGA device output works.
+ */
+ if (pFBInfo->fDisabled)
+ {
+ pFBInfo->fDisabled = false;
+ fireGuestMonitorChangedEvent(pThis->mParent->getEventSource(),
+ GuestMonitorChangedEventType_Enabled,
+ uScreenId,
+ pFBInfo->xOrigin, pFBInfo->yOrigin,
+ pFBInfo->w, pFBInfo->h);
+ }
+ }
+
pFBInfo->fVBVAEnabled = false;
vbvaSetMemoryFlagsHGSMI(uScreenId, 0, false, pFBInfo);
@@ -3796,9 +3974,102 @@ DECLCALLBACK(void) Display::displayVBVAUpdateEnd(PPDMIDISPLAYCONNECTOR pInterfac
}
}
+#ifdef DEBUG_sunlover
+static void logVBVAResize(const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, const DISPLAYFBINFO *pFBInfo)
+{
+ LogRel(("displayVBVAResize: [%d] %s\n"
+ " pView->u32ViewIndex %d\n"
+ " pView->u32ViewOffset 0x%08X\n"
+ " pView->u32ViewSize 0x%08X\n"
+ " pView->u32MaxScreenSize 0x%08X\n"
+ " pScreen->i32OriginX %d\n"
+ " pScreen->i32OriginY %d\n"
+ " pScreen->u32StartOffset 0x%08X\n"
+ " pScreen->u32LineSize 0x%08X\n"
+ " pScreen->u32Width %d\n"
+ " pScreen->u32Height %d\n"
+ " pScreen->u16BitsPerPixel %d\n"
+ " pScreen->u16Flags 0x%04X\n"
+ " pFBInfo->u32Offset 0x%08X\n"
+ " pFBInfo->u32MaxFramebufferSize 0x%08X\n"
+ " pFBInfo->u32InformationSize 0x%08X\n"
+ " pFBInfo->fDisabled %d\n"
+ " xOrigin, yOrigin, w, h: %d,%d %dx%d\n"
+ " pFBInfo->u16BitsPerPixel %d\n"
+ " pFBInfo->pu8FramebufferVRAM %p\n"
+ " pFBInfo->u32LineSize 0x%08X\n"
+ " pFBInfo->flags 0x%04X\n"
+ " pFBInfo->pHostEvents %p\n"
+ " pFBInfo->u32ResizeStatus %d\n"
+ " pFBInfo->fDefaultFormat %d\n"
+ " dirtyRect %d-%d %d-%d\n"
+ " pFBInfo->pendingResize.fPending %d\n"
+ " pFBInfo->pendingResize.pixelFormat %d\n"
+ " pFBInfo->pendingResize.pvVRAM %p\n"
+ " pFBInfo->pendingResize.bpp %d\n"
+ " pFBInfo->pendingResize.cbLine 0x%08X\n"
+ " pFBInfo->pendingResize.w,h %dx%d\n"
+ " pFBInfo->pendingResize.flags 0x%04X\n"
+ " pFBInfo->fVBVAEnabled %d\n"
+ " pFBInfo->cVBVASkipUpdate %d\n"
+ " pFBInfo->vbvaSkippedRect %d-%d %d-%d\n"
+ " pFBInfo->pVBVAHostFlags %p\n"
+ "",
+ pScreen->u32ViewIndex,
+ (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)? "DISABLED": "ENABLED",
+ pView->u32ViewIndex,
+ pView->u32ViewOffset,
+ pView->u32ViewSize,
+ pView->u32MaxScreenSize,
+ pScreen->i32OriginX,
+ pScreen->i32OriginY,
+ pScreen->u32StartOffset,
+ pScreen->u32LineSize,
+ pScreen->u32Width,
+ pScreen->u32Height,
+ pScreen->u16BitsPerPixel,
+ pScreen->u16Flags,
+ pFBInfo->u32Offset,
+ pFBInfo->u32MaxFramebufferSize,
+ pFBInfo->u32InformationSize,
+ pFBInfo->fDisabled,
+ pFBInfo->xOrigin,
+ pFBInfo->yOrigin,
+ pFBInfo->w,
+ pFBInfo->h,
+ pFBInfo->u16BitsPerPixel,
+ pFBInfo->pu8FramebufferVRAM,
+ pFBInfo->u32LineSize,
+ pFBInfo->flags,
+ pFBInfo->pHostEvents,
+ pFBInfo->u32ResizeStatus,
+ pFBInfo->fDefaultFormat,
+ pFBInfo->dirtyRect.xLeft,
+ pFBInfo->dirtyRect.xRight,
+ pFBInfo->dirtyRect.yTop,
+ pFBInfo->dirtyRect.yBottom,
+ pFBInfo->pendingResize.fPending,
+ pFBInfo->pendingResize.pixelFormat,
+ pFBInfo->pendingResize.pvVRAM,
+ pFBInfo->pendingResize.bpp,
+ pFBInfo->pendingResize.cbLine,
+ pFBInfo->pendingResize.w,
+ pFBInfo->pendingResize.h,
+ pFBInfo->pendingResize.flags,
+ pFBInfo->fVBVAEnabled,
+ pFBInfo->cVBVASkipUpdate,
+ pFBInfo->vbvaSkippedRect.xLeft,
+ pFBInfo->vbvaSkippedRect.yTop,
+ pFBInfo->vbvaSkippedRect.xRight,
+ pFBInfo->vbvaSkippedRect.yBottom,
+ pFBInfo->pVBVAHostFlags
+ ));
+}
+#endif /* DEBUG_sunlover */
+
DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM)
{
- LogFlowFunc(("pScreen %p, pvVRAM %p\n", pScreen, pvVRAM));
+ LogRelFlowFunc(("pScreen %p, pvVRAM %p\n", pScreen, pvVRAM));
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
Display *pThis = pDrv->pDisplay;
@@ -3904,7 +4175,7 @@ DECLCALLBACK(int) Display::displayVBVAResize(PPDMIDISPLAYCONNECTOR pInterface, c
if (fNewOrigin)
{
/* VRDP server still need this notification. */
- LogFlowFunc (("Calling VRDP\n"));
+ LogRelFlowFunc (("Calling VRDP\n"));
pThis->mParent->consoleVRDPServer()->SendResize();
}
return VINF_SUCCESS;
@@ -3974,7 +4245,7 @@ DECLCALLBACK(void *) Display::drvQueryInterface(PPDMIBASE pInterface, const cha
DECLCALLBACK(void) Display::drvDestruct(PPDMDRVINS pDrvIns)
{
PDRVMAINDISPLAY pData = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
- LogFlowFunc (("iInstance=%d\n", pDrvIns->iInstance));
+ LogRelFlowFunc (("iInstance=%d\n", pDrvIns->iInstance));
PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
if (pData->pDisplay)
@@ -4002,7 +4273,7 @@ DECLCALLBACK(void) Display::drvDestruct(PPDMDRVINS pDrvIns)
DECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
PDRVMAINDISPLAY pData = PDMINS_2_DATA(pDrvIns, PDRVMAINDISPLAY);
- LogFlowFunc (("iInstance=%d\n", pDrvIns->iInstance));
+ LogRelFlowFunc (("iInstance=%d\n", pDrvIns->iInstance));
PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
/*
@@ -4043,7 +4314,6 @@ DECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint
pData->IConnector.pfnVBVAMousePointerShape = Display::displayVBVAMousePointerShape;
#endif
-
/*
* Get the IDisplayPort interface of the above driver/device.
*/
diff --git a/src/VBox/Main/src-client/GuestCtrlIO.cpp b/src/VBox/Main/src-client/GuestCtrlIO.cpp
deleted file mode 100644
index 2199a32cb..000000000
--- a/src/VBox/Main/src-client/GuestCtrlIO.cpp
+++ /dev/null
@@ -1,441 +0,0 @@
-/* $Id: GuestCtrlIO.cpp $ */
-/** @file
- *
- * IO helper for IGuest COM class implementations.
- */
-
-/*
- * Copyright (C) 2011 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-/******************************************************************************
- * Header Files *
- ******************************************************************************/
-#include "GuestCtrlImplPrivate.h"
-#ifdef DEBUG
-# include "Logging.h"
-# include <iprt/file.h>
-#endif /* DEBUG */
-
-/******************************************************************************
- * Structures and Typedefs *
- ******************************************************************************/
-
-/** @todo *NOT* thread safe yet! */
-/** @todo Add exception handling for STL stuff! */
-
-GuestProcessStreamBlock::GuestProcessStreamBlock()
-{
-
-}
-
-/*
-GuestProcessStreamBlock::GuestProcessStreamBlock(const GuestProcessStreamBlock &otherBlock)
-{
- for (GuestCtrlStreamPairsIter it = otherBlock.m_mapPairs.begin();
- it != otherBlock.end(); it++)
- {
- m_mapPairs[it->first] = new
- if (it->second.pszValue)
- {
- RTMemFree(it->second.pszValue);
- it->second.pszValue = NULL;
- }
- }
-}*/
-
-GuestProcessStreamBlock::~GuestProcessStreamBlock()
-{
- Clear();
-}
-
-/**
- * Destroys the currently stored stream pairs.
- *
- * @return IPRT status code.
- */
-void GuestProcessStreamBlock::Clear()
-{
- m_mapPairs.clear();
-}
-
-#ifdef DEBUG
-void GuestProcessStreamBlock::Dump()
-{
- LogFlowFunc(("Dumping contents of stream block=0x%p (%ld items):\n",
- this, m_mapPairs.size()));
-
- for (GuestCtrlStreamPairMapIterConst it = m_mapPairs.begin();
- it != m_mapPairs.end(); it++)
- {
- LogFlowFunc(("\t%s=%s\n", it->first.c_str(), it->second.mValue.c_str()));
- }
-}
-#endif
-
-/**
- * Returns a 64-bit signed integer of a specified key.
- *
- * @return IPRT status code. VERR_NOT_FOUND if key was not found.
- * @param pszKey Name of key to get the value for.
- * @param piVal Pointer to value to return.
- */
-int GuestProcessStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal)
-{
- AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
- AssertPtrReturn(piVal, VERR_INVALID_POINTER);
- const char *pszValue = GetString(pszKey);
- if (pszValue)
- {
- *piVal = RTStrToInt64(pszValue);
- return VINF_SUCCESS;
- }
- return VERR_NOT_FOUND;
-}
-
-/**
- * Returns a 64-bit integer of a specified key.
- *
- * @return int64_t Value to return, 0 if not found / on failure.
- * @param pszKey Name of key to get the value for.
- */
-int64_t GuestProcessStreamBlock::GetInt64(const char *pszKey)
-{
- int64_t iVal;
- if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
- return iVal;
- return 0;
-}
-
-/**
- * Returns the current number of stream pairs.
- *
- * @return uint32_t Current number of stream pairs.
- */
-size_t GuestProcessStreamBlock::GetCount()
-{
- return m_mapPairs.size();
-}
-
-/**
- * Returns a string value of a specified key.
- *
- * @return uint32_t Pointer to string to return, NULL if not found / on failure.
- * @param pszKey Name of key to get the value for.
- */
-const char* GuestProcessStreamBlock::GetString(const char *pszKey)
-{
- AssertPtrReturn(pszKey, NULL);
-
- try
- {
- GuestCtrlStreamPairMapIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));
- if (itPairs != m_mapPairs.end())
- return itPairs->second.mValue.c_str();
- }
- catch (const std::exception &ex)
- {
- NOREF(ex);
- }
- return NULL;
-}
-
-/**
- * Returns a 32-bit unsigned integer of a specified key.
- *
- * @return IPRT status code. VERR_NOT_FOUND if key was not found.
- * @param pszKey Name of key to get the value for.
- * @param puVal Pointer to value to return.
- */
-int GuestProcessStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal)
-{
- AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
- AssertPtrReturn(puVal, VERR_INVALID_POINTER);
- const char *pszValue = GetString(pszKey);
- if (pszValue)
- {
- *puVal = RTStrToUInt32(pszValue);
- return VINF_SUCCESS;
- }
- return VERR_NOT_FOUND;
-}
-
-/**
- * Returns a 32-bit unsigned integer of a specified key.
- *
- * @return uint32_t Value to return, 0 if not found / on failure.
- * @param pszKey Name of key to get the value for.
- */
-uint32_t GuestProcessStreamBlock::GetUInt32(const char *pszKey)
-{
- uint32_t uVal;
- if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
- return uVal;
- return 0;
-}
-
-/**
- * Sets a value to a key or deletes a key by setting a NULL value.
- *
- * @return IPRT status code.
- * @param pszKey Key name to process.
- * @param pszValue Value to set. Set NULL for deleting the key.
- */
-int GuestProcessStreamBlock::SetValue(const char *pszKey, const char *pszValue)
-{
- AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
-
- int rc = VINF_SUCCESS;
- try
- {
- Utf8Str Utf8Key(pszKey);
-
- /* Take a shortcut and prevent crashes on some funny versions
- * of STL if map is empty initially. */
- if (!m_mapPairs.empty())
- {
- GuestCtrlStreamPairMapIter it = m_mapPairs.find(Utf8Key);
- if (it != m_mapPairs.end())
- m_mapPairs.erase(it);
- }
-
- if (pszValue)
- {
- GuestProcessStreamValue val(pszValue);
- m_mapPairs[Utf8Key] = val;
- }
- }
- catch (const std::exception &ex)
- {
- NOREF(ex);
- }
- return rc;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-GuestProcessStream::GuestProcessStream()
- : m_cbAllocated(0),
- m_cbSize(0),
- m_cbOffset(0),
- m_pbBuffer(NULL)
-{
-
-}
-
-GuestProcessStream::~GuestProcessStream()
-{
- Destroy();
-}
-
-/**
- * Adds data to the internal parser buffer. Useful if there
- * are multiple rounds of adding data needed.
- *
- * @return IPRT status code.
- * @param pbData Pointer to data to add.
- * @param cbData Size (in bytes) of data to add.
- */
-int GuestProcessStream::AddData(const BYTE *pbData, size_t cbData)
-{
- AssertPtrReturn(pbData, VERR_INVALID_POINTER);
- AssertReturn(cbData, VERR_INVALID_PARAMETER);
-
- int rc = VINF_SUCCESS;
-
- /* Rewind the buffer if it's empty. */
- size_t cbInBuf = m_cbSize - m_cbOffset;
- bool const fAddToSet = cbInBuf == 0;
- if (fAddToSet)
- m_cbSize = m_cbOffset = 0;
-
- /* Try and see if we can simply append the data. */
- if (cbData + m_cbSize <= m_cbAllocated)
- {
- memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
- m_cbSize += cbData;
- }
- else
- {
- /* Move any buffered data to the front. */
- cbInBuf = m_cbSize - m_cbOffset;
- if (cbInBuf == 0)
- m_cbSize = m_cbOffset = 0;
- else if (m_cbOffset) /* Do we have something to move? */
- {
- memmove(m_pbBuffer, &m_pbBuffer[m_cbOffset], cbInBuf);
- m_cbSize = cbInBuf;
- m_cbOffset = 0;
- }
-
- /* Do we need to grow the buffer? */
- if (cbData + m_cbSize > m_cbAllocated)
- {
- size_t cbAlloc = m_cbSize + cbData;
- cbAlloc = RT_ALIGN_Z(cbAlloc, _64K);
- void *pvNew = RTMemRealloc(m_pbBuffer, cbAlloc);
- if (pvNew)
- {
- m_pbBuffer = (uint8_t *)pvNew;
- m_cbAllocated = cbAlloc;
- }
- else
- rc = VERR_NO_MEMORY;
- }
-
- /* Finally, copy the data. */
- if (RT_SUCCESS(rc))
- {
- if (cbData + m_cbSize <= m_cbAllocated)
- {
- memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
- m_cbSize += cbData;
- }
- else
- rc = VERR_BUFFER_OVERFLOW;
- }
- }
-
- return rc;
-}
-
-/**
- * Destroys the the internal data buffer.
- */
-void GuestProcessStream::Destroy()
-{
- if (m_pbBuffer)
- {
- RTMemFree(m_pbBuffer);
- m_pbBuffer = NULL;
- }
-
- m_cbAllocated = 0;
- m_cbSize = 0;
- m_cbOffset = 0;
-}
-
-#ifdef DEBUG
-void GuestProcessStream::Dump(const char *pszFile)
-{
- LogFlowFunc(("Dumping contents of stream=0x%p (cbAlloc=%u, cbSize=%u, cbOff=%u) to %s\n",
- m_pbBuffer, m_cbAllocated, m_cbSize, m_cbOffset, pszFile));
-
- RTFILE hFile;
- int rc = RTFileOpen(&hFile, pszFile, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
- if (RT_SUCCESS(rc))
- {
- rc = RTFileWrite(hFile, m_pbBuffer, m_cbSize, NULL /* pcbWritten */);
- RTFileClose(hFile);
- }
-}
-#endif
-
-/**
- * Returns the current offset of the parser within
- * the internal data buffer.
- *
- * @return uint32_t Parser offset.
- */
-uint32_t GuestProcessStream::GetOffset()
-{
- return m_cbOffset;
-}
-
-uint32_t GuestProcessStream::GetSize()
-{
- return m_cbSize;
-}
-
-/**
- * Tries to parse the next upcoming pair block within the internal
- * buffer.
- *
- * Returns VERR_NO_DATA is no data is in internal buffer or buffer has been
- * completely parsed already.
- *
- * Returns VERR_MORE_DATA if current block was parsed (with zero or more pairs
- * stored in stream block) but still contains incomplete (unterminated)
- * data.
- *
- * Returns VINF_SUCCESS if current block was parsed until the next upcoming
- * block (with zero or more pairs stored in stream block).
- *
- * @return IPRT status code.
- * @param streamBlock Reference to guest stream block to fill.
- *
- */
-int GuestProcessStream::ParseBlock(GuestProcessStreamBlock &streamBlock)
-{
- if ( !m_pbBuffer
- || !m_cbSize)
- {
- return VERR_NO_DATA;
- }
-
- AssertReturn(m_cbOffset <= m_cbSize, VERR_INVALID_PARAMETER);
- if (m_cbOffset == m_cbSize)
- return VERR_NO_DATA;
-
- int rc = VINF_SUCCESS;
-
- char *pszOff = (char*)&m_pbBuffer[m_cbOffset];
- char *pszStart = pszOff;
- uint32_t uDistance;
- while (*pszStart)
- {
- size_t pairLen = strlen(pszStart);
- uDistance = (pszStart - pszOff);
- if (m_cbOffset + uDistance + pairLen + 1 >= m_cbSize)
- {
- rc = VERR_MORE_DATA;
- break;
- }
- else
- {
- char *pszSep = strchr(pszStart, '=');
- char *pszVal = NULL;
- if (pszSep)
- pszVal = pszSep + 1;
- if (!pszSep || !pszVal)
- {
- rc = VERR_MORE_DATA;
- break;
- }
-
- /* Terminate the separator so that we can
- * use pszStart as our key from now on. */
- *pszSep = '\0';
-
- rc = streamBlock.SetValue(pszStart, pszVal);
- if (RT_FAILURE(rc))
- return rc;
- }
-
- /* Next pair. */
- pszStart += pairLen + 1;
- }
-
- /* If we did not do any movement but we have stuff left
- * in our buffer just skip the current termination so that
- * we can try next time. */
- uDistance = (pszStart - pszOff);
- if ( !uDistance
- && *pszStart == '\0'
- && m_cbOffset < m_cbSize)
- {
- uDistance++;
- }
- m_cbOffset += uDistance;
-
- return rc;
-}
-
diff --git a/src/VBox/Main/src-client/GuestCtrlImpl.cpp b/src/VBox/Main/src-client/GuestCtrlImpl.cpp
index c25025cd6..42c97541b 100644
--- a/src/VBox/Main/src-client/GuestCtrlImpl.cpp
+++ b/src/VBox/Main/src-client/GuestCtrlImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -16,6 +16,7 @@
*/
#include "GuestImpl.h"
+#include "GuestSessionImpl.h"
#include "GuestCtrlImplPrivate.h"
#include "Global.h"
@@ -24,7 +25,6 @@
#include "VMMDev.h"
#include "AutoCaller.h"
-#include "Logging.h"
#include <VBox/VMMDev.h>
#ifdef VBOX_WITH_GUEST_CONTROL
@@ -41,618 +41,17 @@
#include <memory>
-// public methods only for internal purposes
-/////////////////////////////////////////////////////////////////////////////
-
-#ifdef VBOX_WITH_GUEST_CONTROL
-/**
- * Appends environment variables to the environment block.
- *
- * Each var=value pair is separated by the null character ('\\0'). The whole
- * block will be stored in one blob and disassembled on the guest side later to
- * fit into the HGCM param structure.
- *
- * @returns VBox status code.
- *
- * @param pszEnvVar The environment variable=value to append to the
- * environment block.
- * @param ppvList This is actually a pointer to a char pointer
- * variable which keeps track of the environment block
- * that we're constructing.
- * @param pcbList Pointer to the variable holding the current size of
- * the environment block. (List is a misnomer, go
- * ahead a be confused.)
- * @param pcEnvVars Pointer to the variable holding count of variables
- * stored in the environment block.
- */
-int Guest::prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnvVars)
-{
- int rc = VINF_SUCCESS;
- uint32_t cchEnv = strlen(pszEnv); Assert(cchEnv >= 2);
- if (*ppvList)
- {
- uint32_t cbNewLen = *pcbList + cchEnv + 1; /* Include zero termination. */
- char *pvTmp = (char *)RTMemRealloc(*ppvList, cbNewLen);
- if (pvTmp == NULL)
- rc = VERR_NO_MEMORY;
- else
- {
- memcpy(pvTmp + *pcbList, pszEnv, cchEnv);
- pvTmp[cbNewLen - 1] = '\0'; /* Add zero termination. */
- *ppvList = (void **)pvTmp;
- }
- }
- else
- {
- char *pszTmp;
- if (RTStrAPrintf(&pszTmp, "%s", pszEnv) >= 0)
- {
- *ppvList = (void **)pszTmp;
- /* Reset counters. */
- *pcEnvVars = 0;
- *pcbList = 0;
- }
- }
- if (RT_SUCCESS(rc))
- {
- *pcbList += cchEnv + 1; /* Include zero termination. */
- *pcEnvVars += 1; /* Increase env variable count. */
- }
- return rc;
-}
-
-/**
- * Adds a callback with a user provided data block and an optional progress object
- * to the callback map. A callback is identified by a unique context ID which is used
- * to identify a callback from the guest side.
- *
- * @return IPRT status code.
- * @param pCallback
- * @param puContextID
- */
-int Guest::callbackAdd(const PVBOXGUESTCTRL_CALLBACK pCallback, uint32_t *puContextID)
-{
- AssertPtrReturn(pCallback, VERR_INVALID_PARAMETER);
- /* puContextID is optional. */
-
- int rc = VERR_NOT_FOUND;
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* Create a new context ID and assign it. */
- uint32_t uNewContextID = 0;
- for (;;)
- {
- /* Create a new context ID ... */
- uNewContextID = ASMAtomicIncU32(&mNextContextID);
- if (uNewContextID == UINT32_MAX)
- ASMAtomicUoWriteU32(&mNextContextID, 1000);
- /* Is the context ID already used? Try next ID ... */
- if (!callbackExists(uNewContextID))
- {
- /* Callback with context ID was not found. This means
- * we can use this context ID for our new callback we want
- * to add below. */
- rc = VINF_SUCCESS;
- break;
- }
- }
-
- if (RT_SUCCESS(rc))
- {
- /* Add callback with new context ID to our callback map. */
- mCallbackMap[uNewContextID] = *pCallback;
- Assert(mCallbackMap.size());
-
- /* Report back new context ID. */
- if (puContextID)
- *puContextID = uNewContextID;
- }
-
- return rc;
-}
-
-/**
- * Assigns a host PID to a specified context.
- * Does not do locking!
- *
- * @param uContextID
- * @param uHostPID
- */
-int Guest::callbackAssignHostPID(uint32_t uContextID, uint32_t uHostPID)
-{
- AssertReturn(uContextID, VERR_INVALID_PARAMETER);
- AssertReturn(uHostPID, VERR_INVALID_PARAMETER);
-
- int rc = VINF_SUCCESS;
-
- CallbackMapIter it = mCallbackMap.find(uContextID);
- if (it == mCallbackMap.end())
- return VERR_NOT_FOUND;
-
- it->second.uHostPID = uHostPID;
-
- return VINF_SUCCESS;
-}
-
-/**
- * Destroys the formerly allocated callback data. The callback then
- * needs to get removed from the callback map via callbackRemove().
- * Does not do locking!
- *
- * @param uContextID
- */
-void Guest::callbackDestroy(uint32_t uContextID)
-{
- AssertReturnVoid(uContextID);
-
- CallbackMapIter it = mCallbackMap.find(uContextID);
- if (it != mCallbackMap.end())
- {
- LogFlowFunc(("Callback with CID=%u found\n", uContextID));
- if (it->second.pvData)
- {
- LogFlowFunc(("Destroying callback with CID=%u ...\n", uContextID));
-
- callbackFreeUserData(it->second.pvData);
- it->second.cbData = 0;
- }
- }
-}
-
-/**
- * Removes a callback from the callback map.
- * Does not do locking!
- *
- * @param uContextID
- */
-void Guest::callbackRemove(uint32_t uContextID)
-{
- callbackDestroy(uContextID);
-
- mCallbackMap.erase(uContextID);
-}
-
-bool Guest::callbackExists(uint32_t uContextID)
-{
- AssertReturn(uContextID, false);
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIter it = mCallbackMap.find(uContextID);
- return (it == mCallbackMap.end()) ? false : true;
-}
-
-/**
- * Frees the user data (actual context data) of a callback.
- * Does not do locking!
- *
- * @param pvData Data to free.
- */
-void Guest::callbackFreeUserData(void *pvData)
-{
- if (pvData)
- {
- RTMemFree(pvData);
- pvData = NULL;
- }
-}
-
-/**
- * Retrieves the (generated) host PID of a given callback.
- *
- * @return The host PID, if found, 0 otherwise.
- * @param uContextID Context ID to lookup host PID for.
- * @param puHostPID Where to store the host PID.
- */
-uint32_t Guest::callbackGetHostPID(uint32_t uContextID)
-{
- AssertReturn(uContextID, VERR_INVALID_PARAMETER);
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIterConst it = mCallbackMap.find(uContextID);
- if (it == mCallbackMap.end())
- return 0;
-
- return it->second.uHostPID;
-}
-
-int Guest::callbackGetUserData(uint32_t uContextID, eVBoxGuestCtrlCallbackType *pEnmType,
- void **ppvData, size_t *pcbData)
-{
- AssertReturn(uContextID, VERR_INVALID_PARAMETER);
- /* pEnmType is optional. */
- /* ppvData is optional. */
- /* pcbData is optional. */
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIterConst it = mCallbackMap.find(uContextID);
- if (it == mCallbackMap.end())
- return VERR_NOT_FOUND;
-
- if (pEnmType)
- *pEnmType = it->second.mType;
-
- if ( ppvData
- && it->second.cbData)
- {
- void *pvData = RTMemAlloc(it->second.cbData);
- AssertPtrReturn(pvData, VERR_NO_MEMORY);
- memcpy(pvData, it->second.pvData, it->second.cbData);
- *ppvData = pvData;
- }
-
- if (pcbData)
- *pcbData = it->second.cbData;
-
- return VINF_SUCCESS;
-}
-
-/* Does not do locking! Caller has to take care of it because the caller needs to
- * modify the data ...*/
-void* Guest::callbackGetUserDataMutableRaw(uint32_t uContextID, size_t *pcbData)
-{
- /* uContextID can be 0. */
- /* pcbData is optional. */
-
- CallbackMapIterConst it = mCallbackMap.find(uContextID);
- if (it != mCallbackMap.end())
- {
- if (pcbData)
- *pcbData = it->second.cbData;
- return it->second.pvData;
- }
-
- return NULL;
-}
-
-int Guest::callbackInit(PVBOXGUESTCTRL_CALLBACK pCallback, eVBoxGuestCtrlCallbackType enmType,
- ComPtr<Progress> pProgress)
-{
- AssertPtrReturn(pCallback, VERR_INVALID_POINTER);
- /* Everything else is optional. */
-
- int vrc = VINF_SUCCESS;
- switch (enmType)
- {
- case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START:
- {
- PCALLBACKDATAEXECSTATUS pData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS));
- AssertPtrReturn(pData, VERR_NO_MEMORY);
- RT_BZERO(pData, sizeof(CALLBACKDATAEXECSTATUS));
- pCallback->cbData = sizeof(CALLBACKDATAEXECSTATUS);
- pCallback->pvData = pData;
- break;
- }
-
- case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT:
- {
- PCALLBACKDATAEXECOUT pData = (PCALLBACKDATAEXECOUT)RTMemAlloc(sizeof(CALLBACKDATAEXECOUT));
- AssertPtrReturn(pData, VERR_NO_MEMORY);
- RT_BZERO(pData, sizeof(CALLBACKDATAEXECOUT));
- pCallback->cbData = sizeof(CALLBACKDATAEXECOUT);
- pCallback->pvData = pData;
- break;
- }
-
- case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS:
- {
- PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECINSTATUS));
- AssertPtrReturn(pData, VERR_NO_MEMORY);
- RT_BZERO(pData, sizeof(CALLBACKDATAEXECINSTATUS));
- pCallback->cbData = sizeof(CALLBACKDATAEXECINSTATUS);
- pCallback->pvData = pData;
- break;
- }
-
- default:
- vrc = VERR_INVALID_PARAMETER;
- break;
- }
-
- if (RT_SUCCESS(vrc))
- {
- /* Init/set common stuff. */
- pCallback->mType = enmType;
- pCallback->pProgress = pProgress;
- }
-
- return vrc;
-}
-
-bool Guest::callbackIsCanceled(uint32_t uContextID)
-{
- if (!uContextID)
- return true; /* If no context ID given then take a shortcut. */
-
- ComPtr<IProgress> pProgress;
- {
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIterConst it = mCallbackMap.find(uContextID);
- if (it != mCallbackMap.end())
- pProgress = it->second.pProgress;
- }
-
- if (pProgress)
- {
- BOOL fCanceled = FALSE;
- HRESULT hRC = pProgress->COMGETTER(Canceled)(&fCanceled);
- if ( SUCCEEDED(hRC)
- && !fCanceled)
- {
- return false;
- }
- }
-
- return true; /* No progress / error means canceled. */
-}
-
-bool Guest::callbackIsComplete(uint32_t uContextID)
-{
- AssertReturn(uContextID, true);
-
- ComPtr<IProgress> pProgress;
- {
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIterConst it = mCallbackMap.find(uContextID);
- if (it != mCallbackMap.end())
- pProgress = it->second.pProgress;
- }
-
- if (pProgress)
- {
- BOOL fCompleted = FALSE;
- HRESULT hRC = pProgress->COMGETTER(Completed)(&fCompleted);
- if ( SUCCEEDED(hRC)
- && fCompleted)
- {
- return true;
- }
- }
-
- return false;
-}
-
-int Guest::callbackMoveForward(uint32_t uContextID, const char *pszMessage)
-{
- AssertReturn(uContextID, VERR_INVALID_PARAMETER);
- AssertPtrReturn(pszMessage, VERR_INVALID_PARAMETER);
-
- ComPtr<IProgress> pProgress;
- {
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIterConst it = mCallbackMap.find(uContextID);
- if (it != mCallbackMap.end())
- pProgress = it->second.pProgress;
- }
-
- if (pProgress)
- {
- HRESULT hr = pProgress->SetNextOperation(Bstr(pszMessage).raw(), 1 /* Weight */);
- if (FAILED(hr))
- return VERR_CANCELLED;
-
- return VINF_SUCCESS;
- }
-
- return VERR_NOT_FOUND;
-}
-
-/**
- * Notifies a specified callback about its final status.
- *
- * @return IPRT status code.
- * @param uContextID
- * @param iRC
- * @param pszMessage
- */
-int Guest::callbackNotifyEx(uint32_t uContextID, int iRC, const char *pszMessage)
-{
- AssertReturn(uContextID, VERR_INVALID_PARAMETER);
- if (RT_FAILURE(iRC))
- AssertReturn(pszMessage, VERR_INVALID_PARAMETER);
-
- LogFlowFunc(("Checking whether callback (CID=%u) needs notification iRC=%Rrc, pszMsg=%s\n",
- uContextID, iRC, pszMessage ? pszMessage : "<No message given>"));
-
- ComObjPtr<Progress> pProgress;
- {
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIterConst it = mCallbackMap.find(uContextID);
- if (it != mCallbackMap.end())
- pProgress = it->second.pProgress;
- }
-
-#if 0
- BOOL fCanceled = FALSE;
- HRESULT hRC = pProgress->COMGETTER(Canceled)(&fCanceled);
- if ( SUCCEEDED(hRC)
- && fCanceled)
- {
- /* If progress already canceled do nothing here. */
- return VINF_SUCCESS;
- }
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
#endif
+#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
+#include <VBox/log.h>
- if (pProgress)
- {
- /*
- * Assume we didn't complete to make sure we clean up even if the
- * following call fails.
- */
- BOOL fCompleted = FALSE;
- HRESULT hRC = pProgress->COMGETTER(Completed)(&fCompleted);
- if ( SUCCEEDED(hRC)
- && !fCompleted)
- {
- LogFlowFunc(("Notifying callback with CID=%u, iRC=%Rrc, pszMsg=%s\n",
- uContextID, iRC, pszMessage ? pszMessage : "<No message given>"));
-
- /*
- * To get waitForCompletion completed (unblocked) we have to notify it if necessary (only
- * cancel won't work!). This could happen if the client thread (e.g. VBoxService, thread of a spawned process)
- * is disconnecting without having the chance to sending a status message before, so we
- * have to abort here to make sure the host never hangs/gets stuck while waiting for the
- * progress object to become signalled.
- */
- if (RT_SUCCESS(iRC))
- {
- hRC = pProgress->notifyComplete(S_OK);
- }
- else
- {
- hRC = pProgress->notifyComplete(VBOX_E_IPRT_ERROR /* Must not be S_OK. */,
- COM_IIDOF(IGuest),
- Guest::getStaticComponentName(),
- pszMessage);
- }
-
- LogFlowFunc(("Notified callback with CID=%u returned %Rhrc (0x%x)\n",
- uContextID, hRC, hRC));
- }
- else
- LogFlowFunc(("Callback with CID=%u already notified\n", uContextID));
-
- /*
- * Do *not* NULL pProgress here, because waiting function like executeProcess()
- * will still rely on this object for checking whether they have to give up!
- */
- }
- /* If pProgress is not found (anymore) that's fine.
- * Might be destroyed already. */
- return S_OK;
-}
-/**
- * Notifies all callbacks which are assigned to a certain guest PID to set a certain
- * return/error code and an optional (error) message.
- *
- * @return IPRT status code.
- * @param uGuestPID Guest PID to find all callbacks for.
- * @param iRC Return (error) code to set for the found callbacks.
- * @param pszMessage Optional (error) message to set.
- */
-int Guest::callbackNotifyAllForPID(uint32_t uGuestPID, int iRC, const char *pszMessage)
-{
- AssertReturn(uGuestPID, VERR_INVALID_PARAMETER);
-
- int vrc = VINF_SUCCESS;
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIter it;
- for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
- {
- switch (it->second.mType)
- {
- case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START:
- break;
-
- /* When waiting for process output while the process is destroyed,
- * make sure we also destroy the actual waiting operation (internal progress object)
- * in order to not block the caller. */
- case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT:
- {
- PCALLBACKDATAEXECOUT pItData = (PCALLBACKDATAEXECOUT)it->second.pvData;
- AssertPtr(pItData);
- if (pItData->u32PID == uGuestPID)
- vrc = callbackNotifyEx(it->first, iRC, pszMessage);
- break;
- }
-
- /* When waiting for injecting process input while the process is destroyed,
- * make sure we also destroy the actual waiting operation (internal progress object)
- * in order to not block the caller. */
- case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS:
- {
- PCALLBACKDATAEXECINSTATUS pItData = (PCALLBACKDATAEXECINSTATUS)it->second.pvData;
- AssertPtr(pItData);
- if (pItData->u32PID == uGuestPID)
- vrc = callbackNotifyEx(it->first, iRC, pszMessage);
- break;
- }
-
- default:
- vrc = VERR_INVALID_PARAMETER;
- AssertMsgFailed(("Unknown callback type %d, iRC=%d, message=%s\n",
- it->second.mType, iRC, pszMessage ? pszMessage : "<No message given>"));
- break;
- }
-
- if (RT_FAILURE(vrc))
- break;
- }
-
- return vrc;
-}
-
-int Guest::callbackNotifyComplete(uint32_t uContextID)
-{
- return callbackNotifyEx(uContextID, S_OK, NULL /* No message */);
-}
-
-/**
- * Waits for a callback (using its context ID) to complete.
- *
- * @return IPRT status code.
- * @param uContextID Context ID to wait for.
- * @param lStage Stage to wait for. Specify -1 if no staging is present/required.
- * Specifying a stage is only needed if there's a multi operation progress
- * object to wait for.
- * @param lTimeout Timeout (in ms) to wait for.
- */
-int Guest::callbackWaitForCompletion(uint32_t uContextID, LONG lStage, LONG lTimeout)
-{
- AssertReturn(uContextID, VERR_INVALID_PARAMETER);
-
- /*
- * Wait for the HGCM low level callback until the process
- * has been started (or something went wrong). This is necessary to
- * get the PID.
- */
-
- int vrc = VINF_SUCCESS;
- ComPtr<IProgress> pProgress;
- {
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- CallbackMapIterConst it = mCallbackMap.find(uContextID);
- if (it != mCallbackMap.end())
- pProgress = it->second.pProgress;
- else
- vrc = VERR_NOT_FOUND;
- }
-
- if (RT_SUCCESS(vrc))
- {
- LogFlowFunc(("Waiting for callback completion (CID=%u, Stage=%RI32, timeout=%RI32ms) ...\n",
- uContextID, lStage, lTimeout));
- HRESULT rc;
- if (lStage < 0)
- rc = pProgress->WaitForCompletion(lTimeout);
- else
- rc = pProgress->WaitForOperationCompletion((ULONG)lStage, lTimeout);
- if (SUCCEEDED(rc))
- {
- if (!callbackIsComplete(uContextID))
- vrc = callbackIsCanceled(uContextID)
- ? VERR_CANCELLED : VINF_SUCCESS;
- }
- else
- vrc = VERR_TIMEOUT;
- }
-
- LogFlowFunc(("Callback (CID=%u) completed with rc=%Rrc\n",
- uContextID, vrc));
- return vrc;
-}
+// public methods only for internal purposes
+/////////////////////////////////////////////////////////////////////////////
+#ifdef VBOX_WITH_GUEST_CONTROL
/**
* Static callback function for receiving updates on guest control commands
* from the guest. Acts as a dispatcher for the actual class instance.
@@ -662,6 +61,7 @@ int Guest::callbackWaitForCompletion(uint32_t uContextID, LONG lStage, LONG lTim
* @todo
*
*/
+/* static */
DECLCALLBACK(int) Guest::notifyCtrlDispatcher(void *pvExtension,
uint32_t u32Function,
void *pvParms,
@@ -673,1980 +73,367 @@ DECLCALLBACK(int) Guest::notifyCtrlDispatcher(void *pvExtension,
* No locking, as this is purely a notification which does not make any
* changes to the object state.
*/
-#ifdef DEBUG_andy
- LogFlowFunc(("pvExtension=%p, u32Function=%d, pvParms=%p, cbParms=%d\n",
+ LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n",
pvExtension, u32Function, pvParms, cbParms));
-#endif
ComObjPtr<Guest> pGuest = reinterpret_cast<Guest *>(pvExtension);
+ Assert(!pGuest.isNull());
- int rc = VINF_SUCCESS;
- switch (u32Function)
- {
- case GUEST_DISCONNECTED:
- {
- //LogFlowFunc(("GUEST_DISCONNECTED\n"));
-
- PCALLBACKDATACLIENTDISCONNECTED pCBData = reinterpret_cast<PCALLBACKDATACLIENTDISCONNECTED>(pvParms);
- AssertPtr(pCBData);
- AssertReturn(sizeof(CALLBACKDATACLIENTDISCONNECTED) == cbParms, VERR_INVALID_PARAMETER);
- AssertReturn(CALLBACKDATAMAGIC_CLIENT_DISCONNECTED == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
- rc = pGuest->notifyCtrlClientDisconnected(u32Function, pCBData);
- break;
- }
-
- case GUEST_EXEC_SEND_STATUS:
- {
- //LogFlowFunc(("GUEST_EXEC_SEND_STATUS\n"));
-
- PCALLBACKDATAEXECSTATUS pCBData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvParms);
- AssertPtr(pCBData);
- AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbParms, VERR_INVALID_PARAMETER);
- AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
- rc = pGuest->notifyCtrlExecStatus(u32Function, pCBData);
- break;
- }
-
- case GUEST_EXEC_SEND_OUTPUT:
- {
- //LogFlowFunc(("GUEST_EXEC_SEND_OUTPUT\n"));
-
- PCALLBACKDATAEXECOUT pCBData = reinterpret_cast<PCALLBACKDATAEXECOUT>(pvParms);
- AssertPtr(pCBData);
- AssertReturn(sizeof(CALLBACKDATAEXECOUT) == cbParms, VERR_INVALID_PARAMETER);
- AssertReturn(CALLBACKDATAMAGIC_EXEC_OUT == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
- rc = pGuest->notifyCtrlExecOut(u32Function, pCBData);
- break;
- }
-
- case GUEST_EXEC_SEND_INPUT_STATUS:
- {
- //LogFlowFunc(("GUEST_EXEC_SEND_INPUT_STATUS\n"));
-
- PCALLBACKDATAEXECINSTATUS pCBData = reinterpret_cast<PCALLBACKDATAEXECINSTATUS>(pvParms);
- AssertPtr(pCBData);
- AssertReturn(sizeof(CALLBACKDATAEXECINSTATUS) == cbParms, VERR_INVALID_PARAMETER);
- AssertReturn(CALLBACKDATAMAGIC_EXEC_IN_STATUS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
- rc = pGuest->notifyCtrlExecInStatus(u32Function, pCBData);
- break;
- }
-
- default:
- AssertMsgFailed(("Unknown guest control notification received, u32Function=%u\n", u32Function));
- rc = VERR_INVALID_PARAMETER;
- break;
- }
- return rc;
-}
-
-/* Function for handling the execution start/termination notification. */
-/* Callback can be called several times. */
-int Guest::notifyCtrlExecStatus(uint32_t u32Function,
- PCALLBACKDATAEXECSTATUS pData)
-{
- AssertReturn(u32Function, VERR_INVALID_PARAMETER);
- AssertPtrReturn(pData, VERR_INVALID_PARAMETER);
-
- uint32_t uContextID = pData->hdr.u32ContextID;
- /* The context ID might be 0 in case the guest was not able to fetch
- * actual command. So we can't do much now but report an error. */
-
- /* Scope write locks as much as possible. */
- {
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- LogFlowFunc(("Execution status (CID=%u, pData=0x%p)\n",
- uContextID, pData));
-
- PCALLBACKDATAEXECSTATUS pCallbackData =
- (PCALLBACKDATAEXECSTATUS)callbackGetUserDataMutableRaw(uContextID, NULL /* cbData */);
- if (pCallbackData)
- {
- pCallbackData->u32PID = pData->u32PID;
- pCallbackData->u32Status = pData->u32Status;
- pCallbackData->u32Flags = pData->u32Flags;
- /** @todo Copy void* buffer contents? */
- }
- /* If pCallbackData is NULL this might be an old request for which no user data
- * might exist anymore. */
- }
-
- int vrc = VINF_SUCCESS; /* Function result. */
- int rcCallback = VINF_SUCCESS; /* Callback result. */
- Utf8Str errMsg;
-
- /* Was progress canceled before? */
- bool fCanceled = callbackIsCanceled(uContextID);
- if (!fCanceled)
- {
- /* Handle process map. This needs to be done first in order to have a valid
- * map in case some callback gets notified a bit below. */
-
- uint32_t uHostPID = 0;
-
- /* Note: PIDs never get removed here in case the guest process signalled its
- * end; instead the next call of GetProcessStatus() will remove the PID
- * from the process map after we got the process' final (exit) status.
- * See waitpid() for an example. */
- if (pData->u32PID) /* Only add/change a process if it has a valid PID (>0). */
- {
- uHostPID = callbackGetHostPID(uContextID);
- Assert(uHostPID);
-
- switch (pData->u32Status)
- {
- /* Just reach through flags. */
- case PROC_STS_TES:
- case PROC_STS_TOK:
- vrc = processSetStatus(uHostPID, pData->u32PID,
- (ExecuteProcessStatus_T)pData->u32Status,
- 0 /* Exit code */, pData->u32Flags);
- break;
- /* Interprete u32Flags as the guest process' exit code. */
- default:
- vrc = processSetStatus(uHostPID, pData->u32PID,
- (ExecuteProcessStatus_T)pData->u32Status,
- pData->u32Flags /* Exit code */, 0 /* Flags */);
- break;
- }
- }
-
- if (RT_SUCCESS(vrc))
- {
- /* Do progress handling. */
- switch (pData->u32Status)
- {
- case PROC_STS_STARTED:
- vrc = callbackMoveForward(uContextID, Guest::tr("Waiting for process to exit ..."));
- LogRel(("Guest process (PID %u) started\n", pData->u32PID)); /** @todo Add process name */
- break;
-
- case PROC_STS_TEN: /* Terminated normally. */
- vrc = callbackNotifyComplete(uContextID);
- LogRel(("Guest process (PID %u) exited normally (exit code: %u)\n",
- pData->u32PID, pData->u32Flags)); /** @todo Add process name */
- break;
-
- case PROC_STS_TEA: /* Terminated abnormally. */
- LogRel(("Guest process (PID %u) terminated abnormally (exit code: %u)\n",
- pData->u32PID, pData->u32Flags)); /** @todo Add process name */
- errMsg = Utf8StrFmt(Guest::tr("Process terminated abnormally with status '%u'"),
- pData->u32Flags);
- rcCallback = VERR_GENERAL_FAILURE; /** @todo */
- break;
-
- case PROC_STS_TES: /* Terminated through signal. */
- LogRel(("Guest process (PID %u) terminated through signal (exit code: %u)\n",
- pData->u32PID, pData->u32Flags)); /** @todo Add process name */
- errMsg = Utf8StrFmt(Guest::tr("Process terminated via signal with status '%u'"),
- pData->u32Flags);
- rcCallback = VERR_GENERAL_FAILURE; /** @todo */
- break;
-
- case PROC_STS_TOK:
- LogRel(("Guest process (PID %u) timed out and was killed\n", pData->u32PID)); /** @todo Add process name */
- errMsg = Utf8StrFmt(Guest::tr("Process timed out and was killed"));
- rcCallback = VERR_TIMEOUT;
- break;
-
- case PROC_STS_TOA:
- LogRel(("Guest process (PID %u) timed out and could not be killed\n", pData->u32PID)); /** @todo Add process name */
- errMsg = Utf8StrFmt(Guest::tr("Process timed out and could not be killed"));
- rcCallback = VERR_TIMEOUT;
- break;
-
- case PROC_STS_DWN:
- LogRel(("Guest process (PID %u) killed because system is shutting down\n", pData->u32PID)); /** @todo Add process name */
- /*
- * If u32Flags has ExecuteProcessFlag_IgnoreOrphanedProcesses set, we don't report an error to
- * our progress object. This is helpful for waiters which rely on the success of our progress object
- * even if the executed process was killed because the system/VBoxService is shutting down.
- *
- * In this case u32Flags contains the actual execution flags reached in via Guest::ExecuteProcess().
- */
- if (pData->u32Flags & ExecuteProcessFlag_IgnoreOrphanedProcesses)
- {
- vrc = callbackNotifyComplete(uContextID);
- }
- else
- {
- errMsg = Utf8StrFmt(Guest::tr("Process killed because system is shutting down"));
- rcCallback = VERR_CANCELLED;
- }
- break;
-
- case PROC_STS_ERROR:
- {
- Utf8Str errDetail;
- if (pData->u32PID)
- {
- errDetail = Utf8StrFmt(Guest::tr("Guest process (PID %u) could not be started because of rc=%Rrc"),
- pData->u32PID, pData->u32Flags);
- }
- else
- {
- switch (pData->u32Flags) /* u32Flags member contains the IPRT error code from guest side. */
- {
- case VERR_FILE_NOT_FOUND: /* This is the most likely error. */
- errDetail = Utf8StrFmt(Guest::tr("The specified file was not found on guest"));
- break;
-
- case VERR_PATH_NOT_FOUND:
- errDetail = Utf8StrFmt(Guest::tr("Could not resolve path to specified file was not found on guest"));
- break;
-
- case VERR_BAD_EXE_FORMAT:
- errDetail = Utf8StrFmt(Guest::tr("The specified file is not an executable format on guest"));
- break;
-
- case VERR_AUTHENTICATION_FAILURE:
- errDetail = Utf8StrFmt(Guest::tr("The specified user was not able to logon on guest"));
- break;
-
- case VERR_TIMEOUT:
- errDetail = Utf8StrFmt(Guest::tr("The guest did not respond within time"));
- break;
-
- case VERR_CANCELLED:
- errDetail = Utf8StrFmt(Guest::tr("The execution operation was canceled"));
- break;
-
- case VERR_PERMISSION_DENIED:
- errDetail = Utf8StrFmt(Guest::tr("Invalid user/password credentials"));
- break;
-
- case VERR_MAX_PROCS_REACHED:
- errDetail = Utf8StrFmt(Guest::tr("Guest process could not be started because maximum number of parallel guest processes has been reached"));
- break;
-
- default:
- errDetail = Utf8StrFmt(Guest::tr("Guest process reported error %Rrc"), pData->u32Flags);
- break;
- }
- }
-
- errMsg = Utf8StrFmt(Guest::tr("Process execution failed: "), pData->u32Flags) + errDetail;
- rcCallback = pData->u32Flags; /* Report back guest rc. */
-
- LogRel((errMsg.c_str()));
-
- break;
- }
-
- default:
- vrc = VERR_INVALID_PARAMETER;
- break;
- }
- }
- }
- else
- {
- errMsg = Utf8StrFmt(Guest::tr("Process execution canceled"));
- rcCallback = VERR_CANCELLED;
- }
-
- /* Do we need to handle the callback error? */
- if (RT_FAILURE(rcCallback))
- {
- AssertMsg(!errMsg.isEmpty(), ("Error message must not be empty!\n"));
-
- if (uContextID)
- {
- /* Notify all callbacks which are still waiting on something
- * which is related to the current PID. */
- if (pData->u32PID)
- {
- int rc2 = callbackNotifyAllForPID(pData->u32PID, rcCallback, errMsg.c_str());
- if (RT_FAILURE(rc2))
- {
- LogFlowFunc(("Failed to notify other callbacks for PID=%u\n",
- pData->u32PID));
- if (RT_SUCCESS(vrc))
- vrc = rc2;
- }
- }
-
- /* Let the caller know what went wrong ... */
- int rc2 = callbackNotifyEx(uContextID, rcCallback, errMsg.c_str());
- if (RT_FAILURE(rc2))
- {
- LogFlowFunc(("Failed to notify callback CID=%u for PID=%u\n",
- uContextID, pData->u32PID));
- if (RT_SUCCESS(vrc))
- vrc = rc2;
- }
- }
- else
- {
- /* Since we don't know which context exactly failed all we can do is to shutdown
- * all contexts ... */
- errMsg = Utf8StrFmt(Guest::tr("Client reported critical error %Rrc -- shutting down"),
- pData->u32Flags);
-
- /* Cancel all callbacks. */
- CallbackMapIter it;
- for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
- {
- int rc2 = callbackNotifyEx(it->first, VERR_CANCELLED,
- errMsg.c_str());
- AssertRC(rc2);
- }
- }
-
- LogFlowFunc(("Process (CID=%u, status=%u) reported: %s\n",
- uContextID, pData->u32Status, errMsg.c_str()));
- }
- LogFlowFunc(("Returned with rc=%Rrc, rcCallback=%Rrc\n",
- vrc, rcCallback));
- return vrc;
-}
-
-/* Function for handling the execution output notification. */
-int Guest::notifyCtrlExecOut(uint32_t u32Function,
- PCALLBACKDATAEXECOUT pData)
-{
- AssertReturn(u32Function, VERR_INVALID_PARAMETER);
- AssertPtrReturn(pData, VERR_INVALID_PARAMETER);
-
- uint32_t uContextID = pData->hdr.u32ContextID;
- Assert(uContextID);
-
- /* Scope write locks as much as possible. */
- {
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- LogFlowFunc(("Output status (CID=%u, pData=0x%p)\n",
- uContextID, pData));
-
- PCALLBACKDATAEXECOUT pCallbackData =
- (PCALLBACKDATAEXECOUT)callbackGetUserDataMutableRaw(uContextID, NULL /* cbData */);
- if (pCallbackData)
- {
- pCallbackData->u32PID = pData->u32PID;
- pCallbackData->u32HandleId = pData->u32HandleId;
- pCallbackData->u32Flags = pData->u32Flags;
-
- /* Make sure we really got something! */
- if ( pData->cbData
- && pData->pvData)
- {
- callbackFreeUserData(pCallbackData->pvData);
-
- /* Allocate data buffer and copy it */
- pCallbackData->pvData = RTMemAlloc(pData->cbData);
- pCallbackData->cbData = pData->cbData;
-
- AssertReturn(pCallbackData->pvData, VERR_NO_MEMORY);
- memcpy(pCallbackData->pvData, pData->pvData, pData->cbData);
- }
- else /* Nothing received ... */
- {
- pCallbackData->pvData = NULL;
- pCallbackData->cbData = 0;
- }
- }
- /* If pCallbackData is NULL this might be an old request for which no user data
- * might exist anymore. */
- }
-
- int vrc;
- if (callbackIsCanceled(pData->u32PID))
- {
- vrc = callbackNotifyEx(uContextID, VERR_CANCELLED,
- Guest::tr("The output operation was canceled"));
- }
- else
- vrc = callbackNotifyComplete(uContextID);
-
- return vrc;
-}
-
-/* Function for handling the execution input status notification. */
-int Guest::notifyCtrlExecInStatus(uint32_t u32Function,
- PCALLBACKDATAEXECINSTATUS pData)
-{
- AssertReturn(u32Function, VERR_INVALID_PARAMETER);
- AssertPtrReturn(pData, VERR_INVALID_PARAMETER);
-
- uint32_t uContextID = pData->hdr.u32ContextID;
- Assert(uContextID);
-
- /* Scope write locks as much as possible. */
- {
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- LogFlowFunc(("Input status (CID=%u, pData=0x%p)\n",
- uContextID, pData));
-
- PCALLBACKDATAEXECINSTATUS pCallbackData =
- (PCALLBACKDATAEXECINSTATUS)callbackGetUserDataMutableRaw(uContextID, NULL /* cbData */);
- if (pCallbackData)
- {
- /* Save bytes processed. */
- pCallbackData->cbProcessed = pData->cbProcessed;
- pCallbackData->u32Status = pData->u32Status;
- pCallbackData->u32Flags = pData->u32Flags;
- pCallbackData->u32PID = pData->u32PID;
- }
- /* If pCallbackData is NULL this might be an old request for which no user data
- * might exist anymore. */
- }
-
- return callbackNotifyComplete(uContextID);
-}
-
-int Guest::notifyCtrlClientDisconnected(uint32_t u32Function,
- PCALLBACKDATACLIENTDISCONNECTED pData)
-{
- /* u32Function is 0. */
- AssertPtrReturn(pData, VERR_INVALID_PARAMETER);
-
- uint32_t uContextID = pData->hdr.u32ContextID;
- Assert(uContextID);
-
- LogFlowFunc(("Client disconnected (CID=%u)\n,", uContextID));
-
- return callbackNotifyEx(uContextID, VERR_CANCELLED,
- Guest::tr("Client disconnected"));
-}
-
-uint32_t Guest::processGetGuestPID(uint32_t uHostPID)
-{
- AssertReturn(uHostPID, VERR_INVALID_PARAMETER);
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- GuestProcessMapIter it = mGuestProcessMap.find(uHostPID);
- if (it == mGuestProcessMap.end())
- return 0;
+ /*
+ * For guest control 2.0 using the legacy commands we need to do the following here:
+ * - Get the callback header to access the context ID
+ * - Get the context ID of the callback
+ * - Extract the session ID out of the context ID
+ * - Dispatch the whole stuff to the appropriate session (if still exists)
+ */
- return it->second.mGuestPID;
-}
+ PCALLBACKHEADER pHeader = (PCALLBACKHEADER)pvParms;
+ AssertPtr(pHeader);
-/**
- * Gets guest process information. Removes the process from the map
- * after the process was marked as exited/terminated.
- *
- * @return IPRT status code.
- * @param uHostPID Host PID of guest process to get status for.
- * @param pProcess Where to store the process information. Optional.
- * @param fRemove Flag indicating whether to remove the
- * process from the map when process marked a
- * exited/terminated.
- */
-int Guest::processGetStatus(uint32_t uHostPID, PVBOXGUESTCTRL_PROCESS pProcess,
- bool fRemove)
-{
- AssertReturn(uHostPID, VERR_INVALID_PARAMETER);
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+#ifdef DEBUG
+ LogFlowFunc(("CID=%RU32, uSession=%RU32, uObject=%RU32, uCount=%RU32\n",
+ pHeader->u32ContextID,
+ VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pHeader->u32ContextID),
+ VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pHeader->u32ContextID),
+ VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(pHeader->u32ContextID)));
+#endif
- GuestProcessMapIter it = mGuestProcessMap.find(uHostPID);
- if (it != mGuestProcessMap.end())
+ bool fDispatch = true;
+#ifdef DEBUG
+ /*
+ * Pre-check: If we got a status message with an error and VERR_TOO_MUCH_DATA
+ * it means that that guest could not handle the entire message
+ * because of its exceeding size. This should not happen on daily
+ * use but testcases might try this. It then makes no sense to dispatch
+ * this further because we don't have a valid context ID.
+ */
+ if (u32Function == GUEST_EXEC_SEND_STATUS)
{
- if (pProcess)
- {
- pProcess->mGuestPID = it->second.mGuestPID;
- pProcess->mStatus = it->second.mStatus;
- pProcess->mExitCode = it->second.mExitCode;
- pProcess->mFlags = it->second.mFlags;
- }
+ PCALLBACKDATAEXECSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvParms);
+ AssertPtr(pCallbackData);
+ AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
- /* Only remove processes from our map when they signalled their final
- * status. */
- if ( fRemove
- && ( it->second.mStatus != ExecuteProcessStatus_Undefined
- && it->second.mStatus != ExecuteProcessStatus_Started))
+ if ( pCallbackData->u32Status == PROC_STS_ERROR
+ && ((int)pCallbackData->u32Flags) == VERR_TOO_MUCH_DATA)
{
- mGuestProcessMap.erase(it);
- }
-
- return VINF_SUCCESS;
- }
-
- return VERR_NOT_FOUND;
-}
-
-/**
- * Sets the current status of a guest process.
- *
- * @return IPRT status code.
- * @param uHostPID Host PID of guest process to set status (and guest PID) for.
- * @param uGuestPID Guest PID to assign to the host PID.
- * @param enmStatus Current status to set.
- * @param uExitCode Exit code (if any).
- * @param uFlags Additional flags.
- */
-int Guest::processSetStatus(uint32_t uHostPID, uint32_t uGuestPID,
- ExecuteProcessStatus_T enmStatus, uint32_t uExitCode, uint32_t uFlags)
-{
- AssertReturn(uHostPID, VERR_INVALID_PARAMETER);
- /* Assigning a guest PID is optional. */
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- GuestProcessMapIter it = mGuestProcessMap.find(uHostPID);
- if (it != mGuestProcessMap.end())
- {
- it->second.mGuestPID = uGuestPID;
- it->second.mStatus = enmStatus;
- it->second.mExitCode = uExitCode;
- it->second.mFlags = uFlags;
- }
- else
- {
- VBOXGUESTCTRL_PROCESS process;
-
- /* uGuestPID is optional -- the caller could call this function
- * before the guest process actually was started and a (valid) guest PID
- * was returned. */
- process.mGuestPID = uGuestPID;
- process.mStatus = enmStatus;
- process.mExitCode = uExitCode;
- process.mFlags = uFlags;
+ LogFlowFunc(("Requested command with too much data, skipping dispatching ...\n"));
- mGuestProcessMap[uHostPID] = process;
- }
-
- return VINF_SUCCESS;
-}
-
-HRESULT Guest::setErrorCompletion(int rc)
-{
- HRESULT hRC;
- if (rc == VERR_NOT_FOUND)
- hRC = setErrorNoLog(VBOX_E_VM_ERROR,
- tr("VMM device is not available (is the VM running?)"));
- else if (rc == VERR_CANCELLED)
- hRC = setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("Process execution has been canceled"));
- else if (rc == VERR_TIMEOUT)
- hRC= setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("The guest did not respond within time"));
- else
- hRC = setErrorNoLog(E_UNEXPECTED,
- tr("Waiting for completion failed with error %Rrc"), rc);
- return hRC;
-}
-
-HRESULT Guest::setErrorFromProgress(ComPtr<IProgress> pProgress)
-{
- BOOL fCompleted;
- HRESULT rc = pProgress->COMGETTER(Completed)(&fCompleted);
- ComAssertComRC(rc);
-
- LONG rcProc = S_OK;
- Utf8Str strError;
-
- if (!fCompleted)
- {
- BOOL fCanceled;
- rc = pProgress->COMGETTER(Canceled)(&fCanceled);
- ComAssertComRC(rc);
-
- strError = fCanceled ? Utf8StrFmt(Guest::tr("Process execution was canceled"))
- : Utf8StrFmt(Guest::tr("Process neither completed nor canceled; this shouldn't happen"));
- }
- else
- {
- rc = pProgress->COMGETTER(ResultCode)(&rcProc);
- ComAssertComRC(rc);
-
- if (FAILED(rcProc))
- {
- ProgressErrorInfo info(pProgress);
- strError = info.getText();
+ Assert(pCallbackData->u32PID == 0);
+ fDispatch = false;
}
}
-
- if (FAILED(rcProc))
+#endif
+ int rc = VINF_SUCCESS;
+ if (fDispatch)
{
- AssertMsg(!strError.isEmpty(), ("Error message must not be empty!\n"));
- return setErrorInternal(rcProc,
- this->getClassIID(),
- this->getComponentName(),
- strError,
- false /* aWarning */,
- false /* aLogIt */);
+ rc = pGuest->dispatchToSession(pHeader->u32ContextID, u32Function, pvParms, cbParms);
+ if (RT_SUCCESS(rc))
+ return rc;
}
- return S_OK;
-}
-
-HRESULT Guest::setErrorHGCM(int rc)
-{
- HRESULT hRC;
- if (rc == VERR_INVALID_VM_HANDLE)
- hRC = setErrorNoLog(VBOX_E_VM_ERROR,
- tr("VMM device is not available (is the VM running?)"));
- else if (rc == VERR_NOT_FOUND)
- hRC = setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("The guest execution service is not ready (yet)"));
- else if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
- hRC= setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("The guest execution service is not available"));
- else /* HGCM call went wrong. */
- hRC = setErrorNoLog(E_UNEXPECTED,
- tr("The HGCM call failed with error %Rrc"), rc);
- return hRC;
+ LogFlowFuncLeaveRC(rc);
+ return rc;
}
#endif /* VBOX_WITH_GUEST_CONTROL */
-STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
- ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress)
+STDMETHODIMP Guest::UpdateGuestAdditions(IN_BSTR aSource, ComSafeArrayIn(AdditionsUpdateFlag_T, aFlags), IProgress **aProgress)
{
-/** @todo r=bird: Eventually we should clean up all the timeout parameters
- * in the API and have the same way of specifying infinite waits! */
#ifndef VBOX_WITH_GUEST_CONTROL
ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aCommand);
- CheckComArgOutPointerValid(aPID);
+#else /* VBOX_WITH_GUEST_CONTROL */
+ CheckComArgStrNotEmptyOrNull(aSource);
CheckComArgOutPointerValid(aProgress);
- /* Do not allow anonymous executions (with system rights). */
- if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
- return setError(E_INVALIDARG, tr("No user name specified"));
-
- LogRel(("Executing guest process \"%s\" as user \"%s\" ...\n",
- Utf8Str(aCommand).c_str(), Utf8Str(aUsername).c_str()));
-
- return executeProcessInternal(aCommand, aFlags, ComSafeArrayInArg(aArguments),
- ComSafeArrayInArg(aEnvironment),
- aUsername, aPassword, aTimeoutMS, aPID, aProgress, NULL /* rc */);
-#endif
-}
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
-#ifdef VBOX_WITH_GUEST_CONTROL
-/**
- * Executes and waits for an internal tool (that is, a tool which is integrated into
- * VBoxService, beginning with "vbox_" (e.g. "vbox_ls")) to finish its operation.
- *
- * @return HRESULT
- * @param aTool Name of tool to execute.
- * @param aDescription Friendly description of the operation.
- * @param aFlags Execution flags.
- * @param aUsername Username to execute tool under.
- * @param aPassword The user's password.
- * @param uFlagsToAdd ExecuteProcessFlag flags to add to the execution operation.
- * @param aProgress Pointer which receives the tool's progress object. Optional.
- * @param aPID Pointer which receives the tool's PID. Optional.
- */
-HRESULT Guest::executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription,
- ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG uFlagsToAdd,
- GuestCtrlStreamObjects *pObjStdOut, GuestCtrlStreamObjects *pObjStdErr,
- IProgress **aProgress, ULONG *aPID)
-{
- ComPtr<IProgress> pProgress;
- ULONG uPID;
- ULONG uFlags = ExecuteProcessFlag_Hidden;
- if (uFlagsToAdd)
- uFlags |= uFlagsToAdd;
-
- bool fParseOutput = false;
- if ( ( (uFlags & ExecuteProcessFlag_WaitForStdOut)
- && pObjStdOut)
- || ( (uFlags & ExecuteProcessFlag_WaitForStdErr)
- && pObjStdErr))
+ /* Validate flags. */
+ uint32_t fFlags = AdditionsUpdateFlag_None;
+ if (aFlags)
{
- fParseOutput = true;
+ com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
+ for (size_t i = 0; i < flags.size(); i++)
+ fFlags |= flags[i];
}
- HRESULT hr = ExecuteProcess(aTool,
- uFlags,
- ComSafeArrayInArg(aArguments),
- ComSafeArrayInArg(aEnvironment),
- aUsername, aPassword,
- 0 /* No timeout */,
- &uPID, pProgress.asOutParam());
- if (SUCCEEDED(hr))
+ if (fFlags)
{
- /* Wait for tool being started. */
- hr = pProgress->WaitForOperationCompletion( 0 /* Stage, starting the process */,
- -1 /* No timeout */);
+ if (!(fFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly))
+ return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
}
- if ( SUCCEEDED(hr)
- && !(uFlags & ExecuteProcessFlag_WaitForProcessStartOnly))
+ HRESULT hr = S_OK;
+
+ /* Create an anonymous session. This is required to run the Guest Additions
+ * update process with administrative rights. */
+ ComObjPtr<GuestSession> pSession;
+ int rc = sessionCreate("" /* User */, "" /* Password */, "" /* Domain */,
+ "Updating Guest Additions" /* Name */, pSession);
+ if (RT_FAILURE(rc))
{
- if (!fParseOutput)
+ switch (rc)
{
- if ( !(uFlags & ExecuteProcessFlag_WaitForStdOut)
- && !(uFlags & ExecuteProcessFlag_WaitForStdErr))
- {
- hr = executeWaitForExit(uPID, pProgress, 0 /* No timeout */);
- }
- }
- else
- {
- BOOL fCompleted;
- while ( SUCCEEDED(pProgress->COMGETTER(Completed)(&fCompleted))
- && !fCompleted)
- {
- BOOL fCanceled;
- hr = pProgress->COMGETTER(Canceled)(&fCanceled);
- AssertComRC(hr);
- if (fCanceled)
- {
- hr = setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("%s was cancelled"), Utf8Str(aDescription).c_str());
- break;
- }
-
- if ( (uFlags & ExecuteProcessFlag_WaitForStdOut)
- && pObjStdOut)
- {
- hr = executeStreamParse(uPID, ProcessOutputFlag_None /* StdOut */, *pObjStdOut);
- }
-
- if ( (uFlags & ExecuteProcessFlag_WaitForStdErr)
- && pObjStdErr)
- {
- hr = executeStreamParse(uPID, ProcessOutputFlag_StdErr, *pObjStdErr);
- }
+ case VERR_MAX_PROCS_REACHED:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest sessions (%ld) reached"),
+ VBOX_GUESTCTRL_MAX_SESSIONS);
+ break;
- if (FAILED(hr))
- break;
- }
- }
- }
+ /** @todo Add more errors here. */
- if (SUCCEEDED(hr))
- {
- if (aProgress)
- {
- /* Return the progress to the caller. */
- pProgress.queryInterfaceTo(aProgress);
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest session: %Rrc"), rc);
+ break;
}
- else if (!pProgress.isNull())
- pProgress.setNull();
-
- if (aPID)
- *aPID = uPID;
}
-
- return hr;
-}
-
-/**
- * TODO
- *
- * @return HRESULT
- * @param aObjName
- * @param pStreamBlock
- * @param pObjInfo
- * @param enmAddAttribs
- */
-int Guest::executeStreamQueryFsObjInfo(IN_BSTR aObjName,
- GuestProcessStreamBlock &streamBlock,
- PRTFSOBJINFO pObjInfo,
- RTFSOBJATTRADD enmAddAttribs)
-{
- Utf8Str Utf8ObjName(aObjName);
- int64_t iVal;
- int rc = streamBlock.GetInt64Ex("st_size", &iVal);
- if (RT_SUCCESS(rc))
- pObjInfo->cbObject = iVal;
- /** @todo Add more stuff! */
- return rc;
-}
-
-/**
- * Tries to drain the guest's output and fill it into
- * a guest process stream object for later usage.
- *
- * @todo What's about specifying stderr?
- * @return IPRT status code.
- * @param aPID PID of process to get the output from.
- * @param aFlags Which stream to drain (stdout or stderr).
- * @param pStream Pointer to guest process stream to fill. If NULL,
- * data goes to /dev/null.
- */
-int Guest::executeStreamDrain(ULONG aPID, ULONG aFlags, GuestProcessStream *pStream)
-{
- AssertReturn(aPID, VERR_INVALID_PARAMETER);
- /* pStream is optional. */
-
- int rc = VINF_SUCCESS;
- for (;;)
+ else
{
- SafeArray<BYTE> aData;
- HRESULT hr = getProcessOutputInternal(aPID, aFlags,
- 0 /* Infinite timeout */,
- _64K, ComSafeArrayAsOutParam(aData), &rc);
- if (RT_SUCCESS(rc))
- {
- if ( pStream
- && aData.size())
- {
- rc = pStream->AddData(aData.raw(), aData.size());
- if (RT_UNLIKELY(RT_FAILURE(rc)))
- break;
- }
-
- continue; /* Try one more time. */
- }
- else /* No more output and/or error! */
+ Assert(!pSession.isNull());
+ rc = pSession->queryInfo();
+ if (RT_FAILURE(rc))
{
- if ( rc == VERR_NOT_FOUND
- || rc == VERR_BROKEN_PIPE)
- {
- rc = VINF_SUCCESS;
- }
-
- break;
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Could not query guest session information: %Rrc"), rc);
}
- }
-
- return rc;
-}
-
-/**
- * Tries to retrieve the next stream block of a given stream and
- * drains the process output only as much as needed to get this next
- * stream block.
- *
- * @return IPRT status code.
- * @param ulPID
- * @param ulFlags
- * @param stream
- * @param streamBlock
- */
-int Guest::executeStreamGetNextBlock(ULONG ulPID,
- ULONG ulFlags,
- GuestProcessStream &stream,
- GuestProcessStreamBlock &streamBlock)
-{
- AssertReturn(!streamBlock.GetCount(), VERR_INVALID_PARAMETER);
-
- LogFlowFunc(("Getting next stream block of PID=%u, Flags=%u; cbStrmSize=%u, cbStrmOff=%u\n",
- ulPID, ulFlags, stream.GetSize(), stream.GetOffset()));
-
- int rc;
-
- uint32_t cPairs = 0;
- bool fDrainStream = true;
-
- do
- {
- rc = stream.ParseBlock(streamBlock);
- LogFlowFunc(("Parsing block rc=%Rrc, strmBlockCnt=%ld\n",
- rc, streamBlock.GetCount()));
-
- if (RT_FAILURE(rc)) /* More data needed or empty buffer? */
+ else
{
- if (fDrainStream)
+ try
{
- SafeArray<BYTE> aData;
- HRESULT hr = getProcessOutputInternal(ulPID, ulFlags,
- 0 /* Infinite timeout */,
- _64K, ComSafeArrayAsOutParam(aData), &rc);
- if (SUCCEEDED(hr))
+ ComObjPtr<Progress> pProgress;
+ SessionTaskUpdateAdditions *pTask = new SessionTaskUpdateAdditions(pSession /* GuestSession */,
+ Utf8Str(aSource), fFlags);
+ rc = pSession->startTaskAsync(tr("Updating Guest Additions"), pTask, pProgress);
+ if (RT_SUCCESS(rc))
{
- LogFlowFunc(("Got %ld bytes of additional data\n", aData.size()));
-
- if (RT_FAILURE(rc))
- {
- if (rc == VERR_BROKEN_PIPE)
- rc = VINF_SUCCESS; /* No more data because process already ended. */
- break;
- }
-
- if (aData.size())
- {
- rc = stream.AddData(aData.raw(), aData.size());
- if (RT_UNLIKELY(RT_FAILURE(rc)))
- break;
- }
-
- /* Reset found pairs to not break out too early and let all the new
- * data to be parsed as well. */
- cPairs = 0;
- continue; /* Try one more time. */
+ /* Return progress to the caller. */
+ hr = pProgress.queryInterfaceTo(aProgress);
}
else
- {
- LogFlowFunc(("Getting output returned hr=%Rhrc\n", hr));
-
- /* No more output to drain from stream. */
- if (rc == VERR_NOT_FOUND)
- {
- fDrainStream = false;
- continue;
- }
-
- break;
- }
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Starting task for updating Guest Additions on the guest failed: %Rrc"), rc);
}
- else
+ catch(std::bad_alloc &)
{
- /* We haved drained the stream as much as we can and reached the
- * end of our stream buffer -- that means that there simply is no
- * stream block anymore, which is ok. */
- if (rc == VERR_NO_DATA)
- rc = VINF_SUCCESS;
- break;
+ hr = E_OUTOFMEMORY;
}
}
- else
- cPairs = streamBlock.GetCount();
}
- while (!cPairs);
-
- LogFlowFunc(("Returned with strmBlockCnt=%ld, cPairs=%ld, rc=%Rrc\n",
- streamBlock.GetCount(), cPairs, rc));
- return rc;
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
}
-/**
- * Tries to get the next upcoming value block from a started guest process
- * by first draining its output and then processing the received guest stream.
- *
- * @return IPRT status code.
- * @param ulPID PID of process to get/parse the output from.
- * @param ulFlags ?
- * @param stream Reference to process stream object to use.
- * @param streamBlock Reference that receives the next stream block data.
- *
- */
-int Guest::executeStreamParseNextBlock(ULONG ulPID,
- ULONG ulFlags,
- GuestProcessStream &stream,
- GuestProcessStreamBlock &streamBlock)
-{
- AssertReturn(!streamBlock.GetCount(), VERR_INVALID_PARAMETER);
-
- int rc;
- do
- {
- rc = stream.ParseBlock(streamBlock);
- if (RT_FAILURE(rc))
- break;
- }
- while (!streamBlock.GetCount());
-
- return rc;
-}
+// private methods
+/////////////////////////////////////////////////////////////////////////////
-/**
- * Gets output from a formerly started guest process, tries to parse all of its guest
- * stream (as long as data is available) and returns a stream object which can contain
- * multiple stream blocks (which in turn then can contain key=value pairs).
- *
- * @return HRESULT
- * @param ulPID PID of process to get/parse the output from.
- * @param ulFlags ?
- * @param streamObjects Reference to a guest stream object structure for
- * storing the parsed data.
- */
-HRESULT Guest::executeStreamParse(ULONG ulPID, ULONG ulFlags, GuestCtrlStreamObjects &streamObjects)
+int Guest::dispatchToSession(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData)
{
- GuestProcessStream stream;
- int rc = executeStreamDrain(ulPID, ulFlags, &stream);
- if (RT_SUCCESS(rc))
- {
- do
- {
- /* Try to parse the stream output we gathered until now. If we still need more
- * data the parsing routine will tell us and we just do another poll round. */
- GuestProcessStreamBlock curBlock;
- rc = executeStreamParseNextBlock(ulPID, ulFlags, stream, curBlock);
- if (RT_SUCCESS(rc))
- streamObjects.push_back(curBlock);
- } while (RT_SUCCESS(rc));
-
- if (rc == VERR_NO_DATA) /* End of data reached. */
- rc = VINF_SUCCESS;
- }
+ LogFlowFuncEnter();
- if (RT_FAILURE(rc))
- return setError(VBOX_E_IPRT_ERROR,
- tr("Error while parsing guest output (%Rrc)"), rc);
- return rc;
-}
-
-/**
- * Waits for a fomerly started guest process to exit using its progress
- * object and returns its final status. Returns E_ABORT if guest process
- * was canceled.
- *
- * @return IPRT status code.
- * @param uPID PID of guest process to wait for.
- * @param pProgress Progress object to wait for.
- * @param uTimeoutMS Timeout (in ms) for waiting; use 0 for
- * an indefinite timeout.
- * @param pRetStatus Pointer where to store the final process
- * status. Optional.
- * @param puRetExitCode Pointer where to store the final process
- * exit code. Optional.
- */
-HRESULT Guest::executeWaitForExit(ULONG uPID, ComPtr<IProgress> pProgress, ULONG uTimeoutMS)
-{
- HRESULT rc = S_OK;
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- BOOL fCanceled = FALSE;
- if ( SUCCEEDED(pProgress->COMGETTER(Canceled(&fCanceled)))
- && fCanceled)
+ uint32_t uSessionID = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID);
+#ifdef DEBUG
+ LogFlowFunc(("uSessionID=%RU32 (%RU32 total)\n",
+ uSessionID, mData.mGuestSessions.size()));
+#endif
+ int rc;
+ GuestSessions::const_iterator itSession
+ = mData.mGuestSessions.find(uSessionID);
+ if (itSession != mData.mGuestSessions.end())
{
- return E_ABORT;
- }
+ ComObjPtr<GuestSession> pSession(itSession->second);
+ Assert(!pSession.isNull());
- BOOL fCompleted = FALSE;
- if ( SUCCEEDED(pProgress->COMGETTER(Completed(&fCompleted)))
- && !fCompleted)
- {
- rc = pProgress->WaitForCompletion( !uTimeoutMS
- ? -1 /* No timeout */
- : uTimeoutMS);
- if (FAILED(rc))
- rc = setError(VBOX_E_IPRT_ERROR,
- tr("Waiting for guest process to end failed (%Rhrc)"), rc);
+ alock.release();
+ rc = pSession->dispatchToProcess(uContextID, uFunction, pvData, cbData);
}
+ else
+ rc = VERR_NOT_FOUND;
+ LogFlowFuncLeaveRC(rc);
return rc;
}
-/**
- * Does the actual guest process execution, internal function.
- *
- * @return HRESULT
- * @param aCommand Command line to execute.
- * @param aFlags Execution flags.
- * @param Username Username to execute the process with.
- * @param aPassword The user's password.
- * @param aTimeoutMS Timeout (in ms) to wait for the execution operation.
- * @param aPID Pointer that receives the guest process' PID.
- * @param aProgress Pointer that receives the guest process' progress object.
- * @param pRC Pointer that receives the internal IPRT return code. Optional.
- */
-HRESULT Guest::executeProcessInternal(IN_BSTR aCommand, ULONG aFlags,
- ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC)
+int Guest::sessionRemove(GuestSession *pSession)
{
-/** @todo r=bird: Eventually we should clean up all the timeout parameters
- * in the API and have the same way of specifying infinite waits! */
- using namespace guestControl;
+ LogFlowThisFuncEnter();
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Validate flags. */
- if (aFlags != ExecuteProcessFlag_None)
- {
- if ( !(aFlags & ExecuteProcessFlag_IgnoreOrphanedProcesses)
- && !(aFlags & ExecuteProcessFlag_WaitForProcessStartOnly)
- && !(aFlags & ExecuteProcessFlag_Hidden)
- && !(aFlags & ExecuteProcessFlag_NoProfile)
- && !(aFlags & ExecuteProcessFlag_WaitForStdOut)
- && !(aFlags & ExecuteProcessFlag_WaitForStdErr))
- {
- if (pRC)
- *pRC = VERR_INVALID_PARAMETER;
- return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
- }
- }
+ int rc = VERR_NOT_FOUND;
- HRESULT rc = S_OK;
+ LogFlowFunc(("Closing session (ID=%RU32) ...\n", pSession->getId()));
- try
+ for (GuestSessions::iterator itSessions = mData.mGuestSessions.begin();
+ itSessions != mData.mGuestSessions.end(); ++itSessions)
{
- /*
- * Create progress object. Note that this is a multi operation
- * object to perform the following steps:
- * - Operation 1 (0): Create/start process.
- * - Operation 2 (1): Wait for process to exit.
- * If this progress completed successfully (S_OK), the process
- * started and exited normally. In any other case an error/exception
- * occurred.
- */
- ComObjPtr <Progress> pProgress;
- rc = pProgress.createObject();
- if (SUCCEEDED(rc))
- {
- rc = pProgress->init(static_cast<IGuest*>(this),
- Bstr(tr("Executing process")).raw(),
- TRUE,
- 2, /* Number of operations. */
- Bstr(tr("Starting process ...")).raw()); /* Description of first stage. */
- }
- ComAssertComRC(rc);
-
- /*
- * Prepare process execution.
- */
- int vrc = VINF_SUCCESS;
- Utf8Str Utf8Command(aCommand);
-
- /* Adjust timeout. If set to 0, we define
- * an infinite timeout. */
- if (aTimeoutMS == 0)
- aTimeoutMS = UINT32_MAX;
-
- /* Prepare arguments. */
- char **papszArgv = NULL;
- uint32_t uNumArgs = 0;
- if (aArguments)
+ if (pSession == itSessions->second)
{
- com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments));
- uNumArgs = args.size();
- papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1));
- AssertReturn(papszArgv, E_OUTOFMEMORY);
- for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++)
- vrc = RTUtf16ToUtf8(args[i], &papszArgv[i]);
- papszArgv[uNumArgs] = NULL;
- }
-
- Utf8Str Utf8UserName(aUsername);
- Utf8Str Utf8Password(aPassword);
- uint32_t uHostPID = 0;
-
- if (RT_SUCCESS(vrc))
- {
- uint32_t uContextID = 0;
-
- char *pszArgs = NULL;
- if (uNumArgs > 0)
- vrc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
- if (RT_SUCCESS(vrc))
- {
- uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
-
- /* Prepare environment. */
- void *pvEnv = NULL;
- uint32_t uNumEnv = 0;
- uint32_t cbEnv = 0;
- if (aEnvironment)
- {
- com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment));
-
- for (unsigned i = 0; i < env.size(); i++)
- {
- vrc = prepareExecuteEnv(Utf8Str(env[i]).c_str(), &pvEnv, &cbEnv, &uNumEnv);
- if (RT_FAILURE(vrc))
- break;
- }
- }
+ LogFlowFunc(("Removing session (pSession=%p, ID=%RU32) (now total %ld sessions)\n",
+ (GuestSession *)itSessions->second, itSessions->second->getId(), mData.mGuestSessions.size() - 1));
- if (RT_SUCCESS(vrc))
- {
- VBOXGUESTCTRL_CALLBACK callback;
- vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_START, pProgress);
- if (RT_SUCCESS(vrc))
- vrc = callbackAdd(&callback, &uContextID);
-
- if (RT_SUCCESS(vrc))
- {
- VBOXHGCMSVCPARM paParms[15];
- int i = 0;
- paParms[i++].setUInt32(uContextID);
- paParms[i++].setPointer((void*)Utf8Command.c_str(), (uint32_t)Utf8Command.length() + 1);
- paParms[i++].setUInt32(aFlags);
- paParms[i++].setUInt32(uNumArgs);
- paParms[i++].setPointer((void*)pszArgs, cbArgs);
- paParms[i++].setUInt32(uNumEnv);
- paParms[i++].setUInt32(cbEnv);
- paParms[i++].setPointer((void*)pvEnv, cbEnv);
- paParms[i++].setPointer((void*)Utf8UserName.c_str(), (uint32_t)Utf8UserName.length() + 1);
- paParms[i++].setPointer((void*)Utf8Password.c_str(), (uint32_t)Utf8Password.length() + 1);
-
- /*
- * If the WaitForProcessStartOnly flag is set, we only want to define and wait for a timeout
- * until the process was started - the process itself then gets an infinite timeout for execution.
- * This is handy when we want to start a process inside a worker thread within a certain timeout
- * but let the started process perform lengthly operations then.
- */
- if (aFlags & ExecuteProcessFlag_WaitForProcessStartOnly)
- paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */);
- else
- paParms[i++].setUInt32(aTimeoutMS);
-
- VMMDev *pVMMDev = NULL;
- {
- /* Make sure mParent is valid, so set the read lock while using.
- * Do not keep this lock while doing the actual call, because in the meanwhile
- * another thread could request a write lock which would be a bad idea ... */
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* Forward the information to the VMM device. */
- AssertPtr(mParent);
- pVMMDev = mParent->getVMMDev();
- }
-
- if (pVMMDev)
- {
- LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
- vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
- i, paParms);
- }
- else
- vrc = VERR_INVALID_VM_HANDLE;
- }
- RTMemFree(pvEnv);
- }
- RTStrFree(pszArgs);
- }
-
- if (RT_SUCCESS(vrc))
- {
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /*
- * Generate a host-driven PID so that we immediately can return to the caller and
- * don't need to wait until the guest started the desired process to return the
- * PID generated by the guest OS.
- *
- * The guest PID will later be mapped to the host PID for later lookup.
- */
- vrc = VERR_NOT_FOUND; /* We did not find a host PID yet ... */
-
- uint32_t uTries = 0;
- for (;;)
- {
- /* Create a new context ID ... */
- uHostPID = ASMAtomicIncU32(&mNextHostPID);
- if (uHostPID == UINT32_MAX)
- ASMAtomicUoWriteU32(&mNextHostPID, 1000);
- /* Is the host PID already used? Try next PID ... */
- GuestProcessMapIter it = mGuestProcessMap.find(uHostPID);
- if (it == mGuestProcessMap.end())
- {
- /* Host PID not used (anymore), we're done here ... */
- vrc = VINF_SUCCESS;
- break;
- }
-
- if (++uTries == UINT32_MAX)
- break; /* Don't try too hard. */
- }
-
- if (RT_SUCCESS(vrc))
- vrc = processSetStatus(uHostPID, 0 /* No guest PID yet */,
- ExecuteProcessStatus_Undefined /* Process not started yet */,
- 0 /* uExitCode */, 0 /* uFlags */);
-
- if (RT_SUCCESS(vrc))
- vrc = callbackAssignHostPID(uContextID, uHostPID);
- }
- else
- rc = setErrorHGCM(vrc);
-
- for (unsigned i = 0; i < uNumArgs; i++)
- RTMemFree(papszArgv[i]);
- RTMemFree(papszArgv);
-
- if (RT_FAILURE(vrc))
- rc = VBOX_E_IPRT_ERROR;
- }
+ mData.mGuestSessions.erase(itSessions);
- if (SUCCEEDED(rc))
- {
- /* Return host PID. */
- *aPID = uHostPID;
-
- /* Return the progress to the caller. */
- pProgress.queryInterfaceTo(aProgress);
- }
- else
- {
- if (!pRC) /* Skip logging internal calls. */
- LogRel(("Executing guest process \"%s\" as user \"%s\" failed with %Rrc\n",
- Utf8Command.c_str(), Utf8UserName.c_str(), vrc));
+ rc = VINF_SUCCESS;
+ break;
}
-
- if (pRC)
- *pRC = vrc;
- }
- catch (std::bad_alloc &)
- {
- rc = E_OUTOFMEMORY;
- if (pRC)
- *pRC = VERR_NO_MEMORY;
}
- return rc;
-}
-#endif /* VBOX_WITH_GUEST_CONTROL */
-STDMETHODIMP Guest::SetProcessInput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, ComSafeArrayIn(BYTE, aData), ULONG *aBytesWritten)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgExpr(aPID, aPID > 0);
- CheckComArgOutPointerValid(aBytesWritten);
-
- /* Validate flags. */
- if (aFlags)
- {
- if (!(aFlags & ProcessInputFlag_EndOfFile))
- return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
- }
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- HRESULT rc = S_OK;
-
- try
- {
- VBOXGUESTCTRL_PROCESS process;
- int vrc = processGetStatus(aPID, &process, false /* Don't remove */);
- if (RT_SUCCESS(vrc))
- {
- /* PID exists; check if process is still running. */
- if (process.mStatus != ExecuteProcessStatus_Started)
- rc = setError(VBOX_E_IPRT_ERROR,
- Guest::tr("Cannot inject input to a not running process (PID %u)"), aPID);
- }
- else
- rc = setError(VBOX_E_IPRT_ERROR,
- Guest::tr("Cannot inject input to a non-existent process (PID %u)"), aPID);
-
- if (RT_SUCCESS(vrc))
- {
- uint32_t uContextID = 0;
-
- uint32_t uGuestPID = processGetGuestPID(aPID);
- Assert(uGuestPID);
-
- /*
- * Create progress object.
- * This progress object, compared to the one in executeProgress() above,
- * is only single-stage local and is used to determine whether the operation
- * finished or got canceled.
- */
- ComObjPtr <Progress> pProgress;
- rc = pProgress.createObject();
- if (SUCCEEDED(rc))
- {
- rc = pProgress->init(static_cast<IGuest*>(this),
- Bstr(tr("Setting input for process")).raw(),
- TRUE /* Cancelable */);
- }
- if (FAILED(rc)) throw rc;
- ComAssert(!pProgress.isNull());
-
- /* Adjust timeout. */
- if (aTimeoutMS == 0)
- aTimeoutMS = UINT32_MAX;
-
- VBOXGUESTCTRL_CALLBACK callback;
- vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS, pProgress);
- if (RT_SUCCESS(vrc))
- {
- PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)callback.pvData;
-
- /* Save PID + output flags for later use. */
- pData->u32PID = uGuestPID;
- pData->u32Flags = aFlags;
- }
-
- if (RT_SUCCESS(vrc))
- vrc = callbackAdd(&callback, &uContextID);
-
- if (RT_SUCCESS(vrc))
- {
- com::SafeArray<BYTE> sfaData(ComSafeArrayInArg(aData));
- uint32_t cbSize = sfaData.size();
-
- VBOXHGCMSVCPARM paParms[6];
- int i = 0;
- paParms[i++].setUInt32(uContextID);
- paParms[i++].setUInt32(uGuestPID);
- paParms[i++].setUInt32(aFlags);
- paParms[i++].setPointer(sfaData.raw(), cbSize);
- paParms[i++].setUInt32(cbSize);
-
- {
- VMMDev *pVMMDev = NULL;
- {
- /* Make sure mParent is valid, so set the read lock while using.
- * Do not keep this lock while doing the actual call, because in the meanwhile
- * another thread could request a write lock which would be a bad idea ... */
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* Forward the information to the VMM device. */
- AssertPtr(mParent);
- pVMMDev = mParent->getVMMDev();
- }
-
- if (pVMMDev)
- {
- LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
- vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_SET_INPUT,
- i, paParms);
- if (RT_FAILURE(vrc))
- rc = setErrorHGCM(vrc);
- }
- }
- }
-
- if (RT_SUCCESS(vrc))
- {
- LogFlowFunc(("Waiting for HGCM callback ...\n"));
-
- /*
- * Wait for getting back the input response from the guest.
- */
- vrc = callbackWaitForCompletion(uContextID, -1 /* No staging required */, aTimeoutMS);
- if (RT_SUCCESS(vrc))
- {
- PCALLBACKDATAEXECINSTATUS pExecStatusIn;
- vrc = callbackGetUserData(uContextID, NULL /* We know the type. */,
- (void**)&pExecStatusIn, NULL /* Don't need the size. */);
- if (RT_SUCCESS(vrc))
- {
- AssertPtr(pExecStatusIn);
- switch (pExecStatusIn->u32Status)
- {
- case INPUT_STS_WRITTEN:
- *aBytesWritten = pExecStatusIn->cbProcessed;
- break;
-
- case INPUT_STS_ERROR:
- rc = setError(VBOX_E_IPRT_ERROR,
- tr("Client reported error %Rrc while processing input data"),
- pExecStatusIn->u32Flags);
- break;
-
- case INPUT_STS_TERMINATED:
- rc = setError(VBOX_E_IPRT_ERROR,
- tr("Client terminated while processing input data"));
- break;
-
- case INPUT_STS_OVERFLOW:
- rc = setError(VBOX_E_IPRT_ERROR,
- tr("Client reported buffer overflow while processing input data"));
- break;
-
- default:
- /*AssertReleaseMsgFailed(("Client reported unknown input error, status=%u, flags=%u\n",
- pExecStatusIn->u32Status, pExecStatusIn->u32Flags));*/
- break;
- }
-
- callbackFreeUserData(pExecStatusIn);
- }
- else
- {
- rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("Unable to retrieve process input status data"));
- }
- }
- else
- rc = setErrorCompletion(vrc);
- }
-
- {
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* The callback isn't needed anymore -- just was kept locally. */
- callbackRemove(uContextID);
- }
-
- /* Cleanup. */
- if (!pProgress.isNull())
- pProgress->uninit();
- pProgress.setNull();
- }
- }
- catch (std::bad_alloc &)
- {
- rc = E_OUTOFMEMORY;
- }
+ LogFlowFuncLeaveRC(rc);
return rc;
-#endif
}
-STDMETHODIMP Guest::GetProcessOutput(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, LONG64 aSize, ComSafeArrayOut(BYTE, aData))
+int Guest::sessionCreate(const Utf8Str &strUser, const Utf8Str &strPassword, const Utf8Str &strDomain,
+ const Utf8Str &strSessionName, ComObjPtr<GuestSession> &pGuestSession)
{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- return getProcessOutputInternal(aPID, aFlags, aTimeoutMS,
- aSize, ComSafeArrayOutArg(aData), NULL /* rc */);
-#endif
-}
-
-HRESULT Guest::getProcessOutputInternal(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS,
- LONG64 aSize, ComSafeArrayOut(BYTE, aData), int *pRC)
-{
-/** @todo r=bird: Eventually we should clean up all the timeout parameters
- * in the API and have the same way of specifying infinite waits! */
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgExpr(aPID, aPID > 0);
- if (aSize < 0)
- return setError(E_INVALIDARG, tr("The size argument (%lld) is negative"), aSize);
- if (aSize == 0)
- return setError(E_INVALIDARG, tr("The size (%lld) is zero"), aSize);
- if (aFlags)
- {
- if (!(aFlags & ProcessOutputFlag_StdErr))
- {
- return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
- }
- }
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- HRESULT rc = S_OK;
+ int rc = VERR_MAX_PROCS_REACHED;
+ if (mData.mGuestSessions.size() >= VBOX_GUESTCTRL_MAX_SESSIONS)
+ return rc;
try
{
- VBOXGUESTCTRL_PROCESS proc;
- int vrc = processGetStatus(aPID, &proc, false /* Don't remove */);
- if (RT_FAILURE(vrc))
- {
- rc = setError(VBOX_E_IPRT_ERROR,
- Guest::tr("Guest process (PID %u) does not exist"), aPID);
- }
- else if (proc.mStatus != ExecuteProcessStatus_Started)
- {
- /* If the process is already or still in the process table but does not run yet
- * (or anymore) don't remove it but report back an appropriate error. */
- vrc = VERR_BROKEN_PIPE;
- /* Not getting any output is fine, so don't report an API error (rc)
- * and only signal something through internal error code (vrc). */
- }
+ /* Create a new session ID and assign it. */
+ uint32_t uNewSessionID = 0;
+ uint32_t uTries = 0;
- if (RT_SUCCESS(vrc))
+ for (;;)
{
- uint32_t uContextID = 0;
-
- /*
- * Create progress object.
- * This progress object, compared to the one in executeProgress() above,
- * is only single-stage local and is used to determine whether the operation
- * finished or got canceled.
- */
- ComObjPtr <Progress> pProgress;
- rc = pProgress.createObject();
- if (SUCCEEDED(rc))
- {
- rc = pProgress->init(static_cast<IGuest*>(this),
- Bstr(tr("Getting output for guest process")).raw(),
- TRUE /* Cancelable */);
- }
- if (FAILED(rc)) throw rc;
- ComAssert(!pProgress.isNull());
-
- /* Adjust timeout. */
- if (aTimeoutMS == 0)
- aTimeoutMS = UINT32_MAX;
-
- /* Set handle ID. */
- uint32_t uHandleID = OUTPUT_HANDLE_ID_STDOUT; /* Default */
- if (aFlags & ProcessOutputFlag_StdErr)
- uHandleID = OUTPUT_HANDLE_ID_STDERR;
-
- uint32_t uGuestPID = processGetGuestPID(aPID);
- Assert(uGuestPID);
-
- /** @todo Use a buffer for next iteration if returned data is too big
- * for current read.
- * aSize is bogus -- will be ignored atm! */
- VBOXGUESTCTRL_CALLBACK callback;
- vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT, pProgress);
- if (RT_SUCCESS(vrc))
+ /* Is the context ID already used? */
+ if (!sessionExists(uNewSessionID))
{
- PCALLBACKDATAEXECOUT pData = (PCALLBACKDATAEXECOUT)callback.pvData;
-
- /* Save PID + output flags for later use. */
- pData->u32PID = uGuestPID;
- pData->u32Flags = aFlags;
- }
-
- if (RT_SUCCESS(vrc))
- vrc = callbackAdd(&callback, &uContextID);
-
- if (RT_SUCCESS(vrc))
- {
- VBOXHGCMSVCPARM paParms[5];
- int i = 0;
- paParms[i++].setUInt32(uContextID);
- paParms[i++].setUInt32(uGuestPID);
- paParms[i++].setUInt32(uHandleID);
- paParms[i++].setUInt32(0 /* Flags, none set yet */);
-
- VMMDev *pVMMDev = NULL;
- {
- /* Make sure mParent is valid, so set the read lock while using.
- * Do not keep this lock while doing the actual call, because in the meanwhile
- * another thread could request a write lock which would be a bad idea ... */
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* Forward the information to the VMM device. */
- AssertPtr(mParent);
- pVMMDev = mParent->getVMMDev();
- }
-
- if (pVMMDev)
- {
- LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
- vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_GET_OUTPUT,
- i, paParms);
- }
+ rc = VINF_SUCCESS;
+ break;
}
+ uNewSessionID++;
+ if (uNewSessionID >= VBOX_GUESTCTRL_MAX_SESSIONS)
+ uNewSessionID = 0;
- if (RT_SUCCESS(vrc))
- {
- LogFlowFunc(("Waiting for HGCM callback (timeout=%RI32ms) ...\n", aTimeoutMS));
-
- /*
- * Wait for the HGCM low level callback until the process
- * has been started (or something went wrong). This is necessary to
- * get the PID.
- */
-
- /*
- * Wait for the first output callback notification to arrive.
- */
- vrc = callbackWaitForCompletion(uContextID, -1 /* No staging required */, aTimeoutMS);
- if (RT_SUCCESS(vrc))
- {
- PCALLBACKDATAEXECOUT pExecOut = NULL;
- vrc = callbackGetUserData(uContextID, NULL /* We know the type. */,
- (void**)&pExecOut, NULL /* Don't need the size. */);
- if (RT_SUCCESS(vrc))
- {
- com::SafeArray<BYTE> outputData((size_t)aSize);
-
- if (pExecOut->cbData)
- {
- bool fResize;
-
- /* Do we need to resize the array? */
- if (pExecOut->cbData > aSize)
- {
- fResize = outputData.resize(pExecOut->cbData);
- Assert(fResize);
- }
-
- /* Fill output in supplied out buffer. */
- Assert(outputData.size() >= pExecOut->cbData);
- memcpy(outputData.raw(), pExecOut->pvData, pExecOut->cbData);
- fResize = outputData.resize(pExecOut->cbData); /* Shrink to fit actual buffer size. */
- Assert(fResize);
- }
- else
- {
- /* No data within specified timeout available. */
- bool fResize = outputData.resize(0);
- Assert(fResize);
- }
-
- /* Detach output buffer to output argument. */
- outputData.detachTo(ComSafeArrayOutArg(aData));
-
- callbackFreeUserData(pExecOut);
- }
- else
- {
- rc = setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("Unable to retrieve process output data (%Rrc)"), vrc);
- }
- }
- else
- rc = setErrorCompletion(vrc);
- }
- else
- rc = setErrorHGCM(vrc);
+ if (++uTries == UINT32_MAX)
+ break; /* Don't try too hard. */
+ }
+ if (RT_FAILURE(rc)) throw rc;
- {
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ /* Create the session object. */
+ HRESULT hr = pGuestSession.createObject();
+ if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
- /* The callback isn't needed anymore -- just was kept locally. */
- callbackRemove(uContextID);
- }
+ rc = pGuestSession->init(this, uNewSessionID,
+ strUser, strPassword, strDomain, strSessionName);
+ if (RT_FAILURE(rc)) throw rc;
- /* Cleanup. */
- if (!pProgress.isNull())
- pProgress->uninit();
- pProgress.setNull();
- }
+ mData.mGuestSessions[uNewSessionID] = pGuestSession;
- if (pRC)
- *pRC = vrc;
+ LogFlowFunc(("Added new session (pSession=%p, ID=%RU32), now %ld sessions total\n",
+ (GuestSession *)pGuestSession, uNewSessionID, mData.mGuestSessions.size()));
}
- catch (std::bad_alloc &)
+ catch (int rc2)
{
- rc = E_OUTOFMEMORY;
- if (pRC)
- *pRC = VERR_NO_MEMORY;
+ rc = rc2;
}
+
return rc;
-#endif
}
-STDMETHODIMP Guest::GetProcessStatus(ULONG aPID, ULONG *aExitCode, ULONG *aFlags, ExecuteProcessStatus_T *aStatus)
+inline bool Guest::sessionExists(uint32_t uSessionID)
{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- HRESULT rc = S_OK;
-
- try
- {
- VBOXGUESTCTRL_PROCESS process;
- int vrc = processGetStatus(aPID, &process,
- true /* Remove when terminated */);
- if (RT_SUCCESS(vrc))
- {
- if (aExitCode)
- *aExitCode = process.mExitCode;
- if (aFlags)
- *aFlags = process.mFlags;
- if (aStatus)
- *aStatus = process.mStatus;
- }
- else
- rc = setError(VBOX_E_IPRT_ERROR,
- tr("Process (PID %u) not found!"), aPID);
- }
- catch (std::bad_alloc &)
- {
- rc = E_OUTOFMEMORY;
- }
- return rc;
-#endif
+ GuestSessions::const_iterator itSessions = mData.mGuestSessions.find(uSessionID);
+ return (itSessions == mData.mGuestSessions.end()) ? false : true;
}
-STDMETHODIMP Guest::CopyFromGuest(IN_BSTR aSource, IN_BSTR aDest,
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG aFlags, IProgress **aProgress)
+// implementation of public methods
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP Guest::CreateSession(IN_BSTR aUser, IN_BSTR aPassword, IN_BSTR aDomain, IN_BSTR aSessionName, IGuestSession **aGuestSession)
{
#ifndef VBOX_WITH_GUEST_CONTROL
ReturnComNotImplemented();
#else /* VBOX_WITH_GUEST_CONTROL */
- CheckComArgStrNotEmptyOrNull(aSource);
- CheckComArgStrNotEmptyOrNull(aDest);
- CheckComArgOutPointerValid(aProgress);
- /* Do not allow anonymous executions (with system rights). */
- if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
+ LogFlowFuncEnter();
+
+ /* Do not allow anonymous sessions (with system rights) with official API. */
+ if (RT_UNLIKELY((aUser) == NULL || *(aUser) == '\0'))
return setError(E_INVALIDARG, tr("No user name specified"));
+ CheckComArgOutPointerValid(aGuestSession);
+ /* Rest is optional. */
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* Validate flags. */
- if (aFlags != CopyFileFlag_None)
- {
- if ( !(aFlags & CopyFileFlag_Recursive)
- && !(aFlags & CopyFileFlag_Update)
- && !(aFlags & CopyFileFlag_FollowLinks))
- {
- return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
- }
- }
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = S_OK;
+ HRESULT hr = S_OK;
- ComObjPtr<Progress> progress;
- try
- {
- /* Create the progress object. */
- progress.createObject();
-
- rc = progress->init(static_cast<IGuest*>(this),
- Bstr(tr("Copying file from guest to host")).raw(),
- TRUE /* aCancelable */);
- if (FAILED(rc)) throw rc;
-
- /* Initialize our worker task. */
- GuestTask *pTask = new GuestTask(GuestTask::TaskType_CopyFileFromGuest, this, progress);
- AssertPtr(pTask);
- std::auto_ptr<GuestTask> task(pTask);
-
- /* Assign data - aSource is the source file on the host,
- * aDest reflects the full path on the guest. */
- task->strSource = (Utf8Str(aSource));
- task->strDest = (Utf8Str(aDest));
- task->strUserName = (Utf8Str(aUsername));
- task->strPassword = (Utf8Str(aPassword));
- task->uFlags = aFlags;
-
- rc = task->startThread();
- if (FAILED(rc)) throw rc;
-
- /* Don't destruct on success. */
- task.release();
- }
- catch (HRESULT aRC)
+ ComObjPtr<GuestSession> pSession;
+ int rc = sessionCreate(aUser, aPassword, aDomain, aSessionName, pSession);
+ if (RT_SUCCESS(rc))
{
- rc = aRC;
- }
+ /* Return guest session to the caller. */
+ HRESULT hr2 = pSession.queryInterfaceTo(aGuestSession);
+ if (FAILED(hr2))
+ rc = VERR_COM_OBJECT_NOT_FOUND;
- if (SUCCEEDED(rc))
- {
- /* Return progress to the caller. */
- progress.queryInterfaceTo(aProgress);
+ if (RT_SUCCESS(rc))
+ rc = pSession->queryInfo();
}
- return rc;
-#endif /* VBOX_WITH_GUEST_CONTROL */
-}
-
-STDMETHODIMP Guest::CopyToGuest(IN_BSTR aSource, IN_BSTR aDest,
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG aFlags, IProgress **aProgress)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- CheckComArgStrNotEmptyOrNull(aSource);
- CheckComArgStrNotEmptyOrNull(aDest);
- CheckComArgOutPointerValid(aProgress);
-
- /* Do not allow anonymous executions (with system rights). */
- if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
- return setError(E_INVALIDARG, tr("No user name specified"));
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* Validate flags. */
- if (aFlags != CopyFileFlag_None)
+ if (RT_FAILURE(rc))
{
- if ( !(aFlags & CopyFileFlag_Recursive)
- && !(aFlags & CopyFileFlag_Update)
- && !(aFlags & CopyFileFlag_FollowLinks))
+ switch (rc)
{
- return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
- }
- }
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ case VERR_MAX_PROCS_REACHED:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest sessions (%ld) reached"),
+ VBOX_GUESTCTRL_MAX_SESSIONS);
+ break;
- HRESULT rc = S_OK;
+ /** @todo Add more errors here. */
- ComObjPtr<Progress> pProgress;
- try
- {
- /* Create the progress object. */
- pProgress.createObject();
-
- rc = pProgress->init(static_cast<IGuest*>(this),
- Bstr(tr("Copying file from host to guest")).raw(),
- TRUE /* aCancelable */);
- if (FAILED(rc)) throw rc;
-
- /* Initialize our worker task. */
- GuestTask *pTask = new GuestTask(GuestTask::TaskType_CopyFileToGuest, this, pProgress);
- AssertPtr(pTask);
- std::auto_ptr<GuestTask> task(pTask);
-
- /* Assign data - aSource is the source file on the host,
- * aDest reflects the full path on the guest. */
- task->strSource = (Utf8Str(aSource));
- task->strDest = (Utf8Str(aDest));
- task->strUserName = (Utf8Str(aUsername));
- task->strPassword = (Utf8Str(aPassword));
- task->uFlags = aFlags;
-
- rc = task->startThread();
- if (FAILED(rc)) throw rc;
-
- /* Don't destruct on success. */
- task.release();
- }
- catch (HRESULT aRC)
- {
- rc = aRC;
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest session, rc=%Rrc"), rc);
+ break;
+ }
}
- if (SUCCEEDED(rc))
- {
- /* Return progress to the caller. */
- pProgress.queryInterfaceTo(aProgress);
- }
- return rc;
+ LogFlowFuncLeaveRC(rc);
+ return hr;
#endif /* VBOX_WITH_GUEST_CONTROL */
}
-STDMETHODIMP Guest::UpdateGuestAdditions(IN_BSTR aSource, ULONG aFlags, IProgress **aProgress)
+STDMETHODIMP Guest::FindSession(IN_BSTR aSessionName, ComSafeArrayOut(IGuestSession *, aSessions))
{
#ifndef VBOX_WITH_GUEST_CONTROL
ReturnComNotImplemented();
#else /* VBOX_WITH_GUEST_CONTROL */
- CheckComArgStrNotEmptyOrNull(aSource);
- CheckComArgOutPointerValid(aProgress);
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ CheckComArgOutSafeArrayPointerValid(aSessions);
- /* Validate flags. */
- if (aFlags)
- {
- if (!(aFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly))
- return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
- }
+ LogFlowFuncEnter();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- HRESULT rc = S_OK;
+ Utf8Str strName(aSessionName);
+ std::list < ComObjPtr<GuestSession> > listSessions;
- ComObjPtr<Progress> progress;
- try
+ GuestSessions::const_iterator itSessions = mData.mGuestSessions.begin();
+ while (itSessions != mData.mGuestSessions.end())
{
- /* Create the progress object. */
- progress.createObject();
-
- rc = progress->init(static_cast<IGuest*>(this),
- Bstr(tr("Updating Guest Additions")).raw(),
- TRUE /* aCancelable */);
- if (FAILED(rc)) throw rc;
-
- /* Initialize our worker task. */
- GuestTask *pTask = new GuestTask(GuestTask::TaskType_UpdateGuestAdditions, this, progress);
- AssertPtr(pTask);
- std::auto_ptr<GuestTask> task(pTask);
-
- /* Assign data - in that case aSource is the full path
- * to the Guest Additions .ISO we want to mount. */
- task->strSource = (Utf8Str(aSource));
- task->uFlags = aFlags;
+ if (strName.contains(itSessions->second->getName())) /** @todo Use a (simple) pattern match (IPRT?). */
+ listSessions.push_back(itSessions->second);
+ itSessions++;
+ }
- rc = task->startThread();
- if (FAILED(rc)) throw rc;
+ LogFlowFunc(("Sessions with \"%ls\" = %RU32\n",
+ aSessionName, listSessions.size()));
- /* Don't destruct on success. */
- task.release();
- }
- catch (HRESULT aRC)
+ if (listSessions.size())
{
- rc = aRC;
- }
+ SafeIfaceArray<IGuestSession> sessionIfacs(listSessions);
+ sessionIfacs.detachTo(ComSafeArrayOutArg(aSessions));
- if (SUCCEEDED(rc))
- {
- /* Return progress to the caller. */
- progress.queryInterfaceTo(aProgress);
+ return S_OK;
}
- return rc;
+
+ return setErrorNoLog(VBOX_E_OBJECT_NOT_FOUND,
+ tr("Could not find sessions with name '%ls'"),
+ aSessionName);
#endif /* VBOX_WITH_GUEST_CONTROL */
}
diff --git a/src/VBox/Main/src-client/GuestCtrlImplDir.cpp b/src/VBox/Main/src-client/GuestCtrlImplDir.cpp
deleted file mode 100644
index af1113198..000000000
--- a/src/VBox/Main/src-client/GuestCtrlImplDir.cpp
+++ /dev/null
@@ -1,617 +0,0 @@
-/* $Id: */
-/** @file
- * VirtualBox Guest Control - Guest directory handling.
- */
-
-/*
- * Copyright (C) 2011 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "GuestImpl.h"
-#include "GuestCtrlImplPrivate.h"
-#include "GuestDirEntryImpl.h"
-
-#include "Global.h"
-#include "ConsoleImpl.h"
-#include "ProgressImpl.h"
-#include "VMMDev.h"
-
-#include "AutoCaller.h"
-#include "Logging.h"
-
-#include <VBox/VMMDev.h>
-#ifdef VBOX_WITH_GUEST_CONTROL
-# include <iprt/path.h>
-
-# include <VBox/com/array.h>
-# include <VBox/com/ErrorInfo.h>
-#endif
-
-STDMETHODIMP Guest::DirectoryClose(ULONG aHandle)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- if (directoryHandleExists(aHandle))
- {
- directoryDestroyHandle(aHandle);
- return S_OK;
- }
-
- return setError(VBOX_E_IPRT_ERROR,
- Guest::tr("Directory handle is invalid"));
-#endif
-}
-
-STDMETHODIMP Guest::DirectoryCreate(IN_BSTR aDirectory,
- IN_BSTR aUserName, IN_BSTR aPassword,
- ULONG aMode, ULONG aFlags)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aDirectory);
-
- /* Do not allow anonymous executions (with system rights). */
- if (RT_UNLIKELY((aUserName) == NULL || *(aUserName) == '\0'))
- return setError(E_INVALIDARG, tr("No user name specified"));
-
- LogRel(("Creating guest directory \"%s\" as user \"%s\" ...\n",
- Utf8Str(aDirectory).c_str(), Utf8Str(aUserName).c_str()));
-
- return directoryCreateInternal(aDirectory,
- aUserName, aPassword,
- aMode, aFlags, NULL /* rc */);
-#endif
-}
-
-#ifdef VBOX_WITH_GUEST_CONTROL
-HRESULT Guest::directoryCreateInternal(IN_BSTR aDirectory,
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG aMode, ULONG aFlags, int *pRC)
-{
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aDirectory);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* Validate flags. */
- if (aFlags != DirectoryCreateFlag_None)
- {
- if (!(aFlags & DirectoryCreateFlag_Parents))
- {
- return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
- }
- }
-
- HRESULT hr;
- try
- {
- Utf8Str Utf8Directory(aDirectory);
-
- com::SafeArray<IN_BSTR> args;
- com::SafeArray<IN_BSTR> env;
-
- /*
- * Prepare tool command line.
- */
- if (aFlags & DirectoryCreateFlag_Parents)
- args.push_back(Bstr("--parents").raw()); /* We also want to create the parent directories. */
- if (aMode > 0)
- {
- args.push_back(Bstr("--mode").raw()); /* Set the creation mode. */
-
- char szMode[16];
- RTStrPrintf(szMode, sizeof(szMode), "%o", aMode);
- args.push_back(Bstr(szMode).raw());
- }
- args.push_back(Bstr(Utf8Directory).raw()); /* The directory we want to create. */
-
- ULONG uPID;
- ComPtr<IProgress> pProgress;
- hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_MKDIR).raw(), Bstr("Creating directory").raw(),
- ComSafeArrayAsInParam(args),
- ComSafeArrayAsInParam(env),
- aUsername, aPassword,
- ExecuteProcessFlag_None,
- NULL, NULL,
- pProgress.asOutParam(), &uPID);
- if (SUCCEEDED(hr))
- {
- hr = setErrorFromProgress(pProgress);
- if (SUCCEEDED(hr))
- {
- VBOXGUESTCTRL_PROCESS proc;
- int rc = processGetStatus(uPID, &proc,
- true /* Remove when terminated */);
- if (RT_SUCCESS(rc))
- {
- if ( proc.mStatus != ExecuteProcessStatus_TerminatedNormally
- || proc.mExitCode != 0)
- {
- hr = setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("Could not create directory \"%s\""), Utf8Str(aDirectory).c_str());
- }
- }
- else
- hr = setErrorNoLog(VBOX_E_IPRT_ERROR,
- tr("Unable to retrieve status for creating directory \"%s\""),
- Utf8Str(aDirectory).c_str());
- }
- pProgress.setNull();
- }
- }
- catch (std::bad_alloc &)
- {
- hr = E_OUTOFMEMORY;
- }
- return hr;
-}
-
-/**
- * Creates a new directory handle ID and returns it. Returns VERR_TOO_MUCH_DATA
- * if no free handles left, otherwise VINF_SUCCESS (or some other IPRT error).
- *
- * @return IPRT status code.
- * @param puHandle Pointer where the handle gets stored to. Optional.
- * @param uPID PID of guest process running the associated "vbox_ls".
- * @param aDirectory Directory the handle is assigned to.
- * @param aFilter Directory filter. Optional.
- * @param uFlags Directory open flags.
- *
- */
-int Guest::directoryCreateHandle(ULONG *puHandle, ULONG uPID,
- IN_BSTR aDirectory, IN_BSTR aFilter, ULONG uFlags)
-{
- AssertReturn(uPID, VERR_INVALID_PARAMETER);
- CheckComArgStrNotEmptyOrNull(aDirectory);
- /* aFilter is optional. */
- /* uFlags are optional. */
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- int rc = VERR_TOO_MUCH_DATA;
- for (uint32_t i = 0; i < UINT32_MAX - 1; i++)
- {
- /* Create a new context ID ... */
- uint32_t uHandleTry = ASMAtomicIncU32(&mNextDirectoryID);
- GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandleTry);
- if (it == mGuestDirectoryMap.end()) /* We found a free slot ... */
- {
- mGuestDirectoryMap[uHandleTry].mDirectory = aDirectory;
- mGuestDirectoryMap[uHandleTry].mFilter = aFilter;
- mGuestDirectoryMap[uHandleTry].mPID = uPID;
- mGuestDirectoryMap[uHandleTry].mFlags = uFlags;
- Assert(mGuestDirectoryMap.size());
-
- rc = VINF_SUCCESS;
-
- if (puHandle)
- *puHandle = uHandleTry;
- break;
- }
- }
-
- return rc;
-}
-
-/**
- * Destroys a previously created directory handle and its
- * associated data.
- *
- * @return IPRT status code.
- * @param uHandle Handle to destroy.
- */
-void Guest::directoryDestroyHandle(uint32_t uHandle)
-{
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
- if (it != mGuestDirectoryMap.end())
- {
- /* Destroy raw guest stream buffer - not used
- * anymore. */
- it->second.mStream.Destroy();
-
- /* Remove callback context (not used anymore). */
- mGuestDirectoryMap.erase(it);
- }
-}
-
-#if 0
-STDMETHODIMP Guest::DirectoryExists(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aDirectory);
-
- /* Do not allow anonymous executions (with system rights). */
- if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
- return setError(E_INVALIDARG, tr("No user name specified"));
-
- return directoryExistsInternal(aDirectory,
- aUsername, aPassword, aExists);
-#endif
-}
-#endif
-
-#ifdef VBOX_WITH_GUEST_CONTROL
-HRESULT Guest::directoryExistsInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
-{
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aDirectory);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- int rc;
- HRESULT hr = directoryQueryInfoInternal(aDirectory,
- aUsername, aPassword,
- NULL /* No RTFSOBJINFO needed */,
- RTFSOBJATTRADD_NOTHING, &rc);
- if (SUCCEEDED(hr))
- {
- switch (rc)
- {
- case VINF_SUCCESS:
- *aExists = TRUE;
- break;
-
- case VERR_PATH_NOT_FOUND:
- *aExists = FALSE;
- break;
-
- default:
- hr = setError(VBOX_E_IPRT_ERROR,
- Guest::tr("Unable to query directory existence (%Rrc)"), rc);
- break;
- }
- }
- return hr;
-}
-#endif
-
-/**
- * Gets the associated PID from a directory handle.
- *
- * @return uint32_t Associated PID, 0 if handle not found/invalid.
- * @param uHandle Directory handle to get PID for.
- */
-uint32_t Guest::directoryGetPID(uint32_t uHandle)
-{
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
- if (it != mGuestDirectoryMap.end())
- return it->second.mPID;
-
- return 0;
-}
-
-/**
- * Returns the next directory entry of an open guest directory.
- * Returns VERR_NO_DATA if no more entries available or VERR_NOT_FOUND
- * if directory handle is invalid.
- *
- * @return IPRT status code.
- * @param uHandle Directory handle to get entry for.
- * @param streamBlock Reference that receives the next stream block data.
- */
-int Guest::directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock)
-{
- // LOCK DOES NOT WORK HERE!?
- //AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
- if (it != mGuestDirectoryMap.end())
- {
-#ifdef DEBUG
- it->second.mStream.Dump("c:\\temp\\stream.txt");
-#endif
- return executeStreamGetNextBlock(it->second.mPID,
- ProcessOutputFlag_None /* StdOut */,
- it->second.mStream, streamBlock);
- }
-
- return VERR_NOT_FOUND;
-}
-
-/**
- * Checks whether a specified directory handle exists (is valid)
- * or not.
- *
- * @return bool True if handle exists, false if not.
- * @param uHandle Directory handle to check.
- */
-bool Guest::directoryHandleExists(uint32_t uHandle)
-{
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
- if (it != mGuestDirectoryMap.end())
- return true;
-
- return false;
-}
-#endif /* VBOX_WITH_GUEST_CONTROL */
-
-STDMETHODIMP Guest::DirectoryOpen(IN_BSTR aDirectory, IN_BSTR aFilter,
- ULONG aFlags, IN_BSTR aUserName, IN_BSTR aPassword,
- ULONG *aHandle)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aDirectory);
- CheckComArgNotNull(aHandle);
-
- /* Do not allow anonymous executions (with system rights). */
- if (RT_UNLIKELY((aUserName) == NULL || *(aUserName) == '\0'))
- return setError(E_INVALIDARG, tr("No user name specified"));
-
- return directoryOpenInternal(aDirectory, aFilter,
- aFlags,
- aUserName, aPassword,
- aHandle, NULL /* rc */);
-#endif
-}
-
-#ifdef VBOX_WITH_GUEST_CONTROL
-HRESULT Guest::directoryOpenInternal(IN_BSTR aDirectory, IN_BSTR aFilter,
- ULONG aFlags,
- IN_BSTR aUsername, IN_BSTR aPassword,
- ULONG *aHandle, int *pRC)
-{
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aDirectory);
- CheckComArgNotNull(aHandle);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* Validate flags. No flags supported yet. */
- if (aFlags != DirectoryOpenFlag_None)
- return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
-
- HRESULT hr = S_OK;
- try
- {
- Utf8Str Utf8Directory(aDirectory);
- Utf8Str Utf8Filter(aFilter);
-
- com::SafeArray<IN_BSTR> args;
- com::SafeArray<IN_BSTR> env;
-
- /*
- * Prepare tool command line.
- */
-
- /* We need to get output which is machine-readable in form
- * of "key=value\0..key=value\0\0". */
- args.push_back(Bstr("--machinereadable").raw());
-
- /* We want the long output format. Handy for getting a lot of
- * details we could (should?) use (later). */
- args.push_back(Bstr("-l").raw());
-
- /* As we want to keep this stuff simple we don't do recursive (-R)
- * or dereferencing (--dereference) lookups here. This has to be done by
- * the user. */
-
- /* Construct and hand in actual directory name + filter we want to open. */
- char *pszDirectoryFinal;
- if (Utf8Filter.isEmpty())
- pszDirectoryFinal = RTStrDup(Utf8Directory.c_str());
- else
- pszDirectoryFinal = RTPathJoinA(Utf8Directory.c_str(), Utf8Filter.c_str());
- if (!pszDirectoryFinal)
- return setError(E_OUTOFMEMORY, tr("Out of memory while allocating final directory"));
-
- args.push_back(Bstr(pszDirectoryFinal).raw()); /* The directory we want to open. */
- RTStrFree(pszDirectoryFinal);
-
- ULONG uPID;
- /* We only start the directory listing and requesting stdout data but don't get its
- * data here; this is done in sequential IGuest::DirectoryRead calls then. */
- hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_LS).raw(), Bstr("Opening directory").raw(),
- ComSafeArrayAsInParam(args),
- ComSafeArrayAsInParam(env),
- aUsername, aPassword,
- ExecuteProcessFlag_WaitForStdOut,
- NULL, NULL,
- NULL /* Progress */, &uPID);
- if (SUCCEEDED(hr))
- {
- /* Assign new directory handle ID. */
- ULONG uHandleNew;
- int rc = directoryCreateHandle(&uHandleNew, uPID,
- aDirectory, aFilter, aFlags);
- if (RT_SUCCESS(rc))
- {
- *aHandle = uHandleNew;
- }
- else
- hr = setError(VBOX_E_IPRT_ERROR,
- tr("Unable to create guest directory handle (%Rrc)"), rc);
- if (pRC)
- *pRC = rc;
- }
- }
- catch (std::bad_alloc &)
- {
- hr = E_OUTOFMEMORY;
- }
- return hr;
-}
-
-HRESULT Guest::directoryQueryInfoInternal(IN_BSTR aDirectory,
- IN_BSTR aUsername, IN_BSTR aPassword,
- PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs,
- int *pRC)
-{
- using namespace guestControl;
-
- /** @todo Search directory cache first? */
-
- CheckComArgStrNotEmptyOrNull(aDirectory);
- /* aUsername is optional. */
- /* aPassword is optional. */
- /* aObjInfo is optional. */
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- HRESULT hr = S_OK;
- try
- {
- Utf8Str Utf8Dir(aDirectory);
- Utf8Str Utf8Username(aUsername);
- Utf8Str Utf8Password(aPassword);
-
- com::SafeArray<IN_BSTR> args;
- com::SafeArray<IN_BSTR> env;
-
- /*
- * Prepare tool command line.
- */
-
- /* We need to get output which is machine-readable in form
- * of "key=value\0..key=value\0\0". */
- args.push_back(Bstr("--machinereadable").raw());
-
- /* Only the actual file name to chekc is needed for now. */
- args.push_back(Bstr(Utf8Dir).raw());
-
- /*
- * Execute guest process.
- */
- ULONG uPID;
- ComPtr<IProgress> pProgress;
- GuestCtrlStreamObjects stdOut;
- hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying directory information").raw(),
- ComSafeArrayAsInParam(args),
- ComSafeArrayAsInParam(env),
- aUsername, aPassword,
- ExecuteProcessFlag_WaitForStdOut,
- &stdOut, NULL /* stdErr */,
- pProgress.asOutParam(), &uPID);
- if (SUCCEEDED(hr))
- {
- hr = setErrorFromProgress(pProgress);
- if (SUCCEEDED(hr))
- {
- int rc = VINF_SUCCESS;
- if (stdOut.size())
- {
- const char *pszFsType = stdOut[0].GetString("ftype");
- if (!pszFsType) /* Attribute missing? */
- rc = VERR_PATH_NOT_FOUND;
- if ( RT_SUCCESS(rc)
- && strcmp(pszFsType, "d")) /* Directory? */
- {
- rc = VERR_PATH_NOT_FOUND;
- /* This is not critical for Main, so don't set hr --
- * we will take care of rc then. */
- }
- if ( RT_SUCCESS(rc)
- && aObjInfo) /* Do we want object details? */
- {
- rc = executeStreamQueryFsObjInfo(aDirectory, stdOut[0],
- aObjInfo, enmAddAttribs);
- }
- }
- else
- rc = VERR_NO_DATA;
-
- if (pRC)
- *pRC = rc;
- }
-
- pProgress.setNull();
- }
- }
- catch (std::bad_alloc &)
- {
- hr = E_OUTOFMEMORY;
- }
- return hr;
-}
-#endif /* VBOX_WITH_GUEST_CONTROL */
-
-STDMETHODIMP Guest::DirectoryRead(ULONG aHandle, IGuestDirEntry **aDirEntry)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgOutPointerValid(aDirEntry);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- HRESULT hr = S_OK;
- try
- {
- GuestProcessStreamBlock streamBlock;
- int rc = directoryGetNextEntry(aHandle, streamBlock);
- if (RT_SUCCESS(rc))
- {
- if (streamBlock.GetCount())
- {
- ComObjPtr <GuestDirEntry> pDirEntry;
- hr = pDirEntry.createObject();
- ComAssertComRC(hr);
-
- hr = pDirEntry->init(this, streamBlock);
- if (SUCCEEDED(hr))
- {
- pDirEntry.queryInterfaceTo(aDirEntry);
- }
- else
- {
-#ifdef DEBUG
- streamBlock.Dump();
-#endif
- hr = VBOX_E_FILE_ERROR;
- }
- }
- else
- {
- /* No more directory entries to read. That's fine. */
- hr = E_ABORT; /** @todo Find/define a better rc! */
- }
- }
- else
- hr = setError(VBOX_E_IPRT_ERROR,
- Guest::tr("Failed getting next directory entry (%Rrc)"), rc);
- }
- catch (std::bad_alloc &)
- {
- hr = E_OUTOFMEMORY;
- }
- return hr;
-#endif
-}
-
diff --git a/src/VBox/Main/src-client/GuestCtrlImplFile.cpp b/src/VBox/Main/src-client/GuestCtrlImplFile.cpp
deleted file mode 100644
index 2ed1252fd..000000000
--- a/src/VBox/Main/src-client/GuestCtrlImplFile.cpp
+++ /dev/null
@@ -1,246 +0,0 @@
-/* $Id: */
-/** @file
- * VirtualBox Guest Control - Guest file handling.
- */
-
-/*
- * Copyright (C) 2011 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "GuestImpl.h"
-#include "GuestCtrlImplPrivate.h"
-
-#include "Global.h"
-#include "ConsoleImpl.h"
-#include "ProgressImpl.h"
-#include "VMMDev.h"
-
-#include "AutoCaller.h"
-#include "Logging.h"
-
-#include <VBox/VMMDev.h>
-#ifdef VBOX_WITH_GUEST_CONTROL
-# include <VBox/com/array.h>
-# include <VBox/com/ErrorInfo.h>
-#endif
-
-STDMETHODIMP Guest::FileExists(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aFile);
-
- /* Do not allow anonymous executions (with system rights). */
- if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
- return setError(E_INVALIDARG, tr("No user name specified"));
-
- /* If filename ends with a slash or backslash we assume it's a directory and
- * call the appropriate function instead the regular one just for files. */
- Utf8Str Utf8File(aFile);
- if ( Utf8File.endsWith("/")
- || Utf8File.endsWith("\\"))
- {
- return directoryExistsInternal(aFile, aUsername, aPassword, aExists);
- }
- return fileExistsInternal(aFile,
- aUsername, aPassword, aExists);
-#endif
-}
-
-#ifdef VBOX_WITH_GUEST_CONTROL
-HRESULT Guest::fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
-{
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aFile);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- int rc;
- HRESULT hr = fileQueryInfoInternal(aFile,
- aUsername, aPassword,
- NULL /* No RTFSOBJINFO needed */,
- RTFSOBJATTRADD_NOTHING, &rc);
- if (SUCCEEDED(hr))
- {
- switch (rc)
- {
- case VINF_SUCCESS:
- *aExists = TRUE;
- break;
-
- case VERR_FILE_NOT_FOUND:
- *aExists = FALSE;
- break;
-
- default:
- hr = setError(VBOX_E_IPRT_ERROR,
- Guest::tr("Unable to query file existence (%Rrc)"), rc);
- break;
- }
- }
- return hr;
-}
-
-HRESULT Guest::fileQueryInfoInternal(IN_BSTR aFile,
- IN_BSTR aUsername, IN_BSTR aPassword,
- PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs,
- int *pRC)
-{
- using namespace guestControl;
-
- /* aUsername is optional. */
- /* aPassword is optional. */
- /* aObjInfo is optional. */
-
- HRESULT hr;
- try
- {
- Utf8Str Utf8File(aFile);
- Utf8Str Utf8Username(aUsername);
- Utf8Str Utf8Password(aPassword);
-
- com::SafeArray<IN_BSTR> args;
- com::SafeArray<IN_BSTR> env;
-
- /*
- * Prepare tool command line.
- */
-
- /* We need to get output which is machine-readable in form
- * of "key=value\0..key=value\0\0". */
- args.push_back(Bstr("--machinereadable").raw());
-
- /* Only the actual file name to chekc is needed for now. */
- args.push_back(Bstr(Utf8File).raw());
-
- /*
- * Execute guest process.
- */
- ULONG uPID;
- GuestCtrlStreamObjects stdOut;
- ComPtr<IProgress> pProgress;
- hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying file information").raw(),
- ComSafeArrayAsInParam(args),
- ComSafeArrayAsInParam(env),
- aUsername, aPassword,
- ExecuteProcessFlag_WaitForStdOut,
- &stdOut, NULL,
- pProgress.asOutParam(), &uPID);
- if (SUCCEEDED(hr))
- {
- hr = setErrorFromProgress(pProgress);
- if (SUCCEEDED(hr))
- {
- int rc = VINF_SUCCESS;
- if (stdOut.size())
- {
-#if 0
- /* Dump the parsed stream contents to Log(). */
- stdOut[0].Dump();
-#endif
- const char *pszFsType = stdOut[0].GetString("ftype");
- if (!pszFsType) /* Was an object found at all? */
- rc = VERR_FILE_NOT_FOUND;
- if ( RT_SUCCESS(rc)
- && strcmp(pszFsType, "-")) /* Regular file? */
- {
- rc = VERR_FILE_NOT_FOUND;
- /* This is not critical for Main, so don't set hr --
- * we will take care of rc then. */
- }
- if ( RT_SUCCESS(rc)
- && aObjInfo) /* Do we want object details? */
- {
- rc = executeStreamQueryFsObjInfo(aFile, stdOut[0],
- aObjInfo, enmAddAttribs);
- }
- }
- else
- rc = VERR_NO_DATA;
-
- if (pRC)
- *pRC = rc;
- }
-
- pProgress.setNull();
- }
- }
- catch (std::bad_alloc &)
- {
- hr = E_OUTOFMEMORY;
- }
-
- return hr;
-}
-#endif /* VBOX_WITH_GUEST_CONTROL */
-
-STDMETHODIMP Guest::FileQuerySize(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize)
-{
-#ifndef VBOX_WITH_GUEST_CONTROL
- ReturnComNotImplemented();
-#else /* VBOX_WITH_GUEST_CONTROL */
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aFile);
-
- /* Do not allow anonymous executions (with system rights). */
- if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
- return setError(E_INVALIDARG, tr("No user name specified"));
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- return fileQuerySizeInternal(aFile,
- aUsername, aPassword, aSize);
-#endif
-}
-
-#ifdef VBOX_WITH_GUEST_CONTROL
-HRESULT Guest::fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize)
-{
- using namespace guestControl;
-
- CheckComArgStrNotEmptyOrNull(aFile);
-
- int rc;
- RTFSOBJINFO objInfo;
- HRESULT hr = fileQueryInfoInternal(aFile,
- aUsername, aPassword,
- &objInfo, RTFSOBJATTRADD_NOTHING, &rc);
- if (SUCCEEDED(hr))
- {
- switch (rc)
- {
- case VINF_SUCCESS:
- *aSize = objInfo.cbObject;
- break;
-
- case VERR_FILE_NOT_FOUND:
- hr = setError(VBOX_E_IPRT_ERROR,
- Guest::tr("File not found"));
- break;
-
- default:
- hr = setError(VBOX_E_IPRT_ERROR,
- Guest::tr("Unable to query file size (%Rrc)"), rc);
- break;
- }
- }
-
- return hr;
-}
-#endif /* VBOX_WITH_GUEST_CONTROL */
-
diff --git a/src/VBox/Main/src-client/GuestCtrlImplTasks.cpp b/src/VBox/Main/src-client/GuestCtrlImplTasks.cpp
deleted file mode 100644
index a981cd5a6..000000000
--- a/src/VBox/Main/src-client/GuestCtrlImplTasks.cpp
+++ /dev/null
@@ -1,1050 +0,0 @@
-/* $Id: */
-/** @file
- * VirtualBox Guest Control - Threaded operations (tasks).
- */
-
-/*
- * Copyright (C) 2011 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include <memory>
-
-#include "GuestImpl.h"
-#include "GuestCtrlImplPrivate.h"
-
-#include "Global.h"
-#include "ConsoleImpl.h"
-#include "ProgressImpl.h"
-#include "VMMDev.h"
-
-#include "AutoCaller.h"
-#include "Logging.h"
-
-#include <VBox/VMMDev.h>
-#ifdef VBOX_WITH_GUEST_CONTROL
-# include <VBox/com/array.h>
-# include <VBox/com/ErrorInfo.h>
-#endif
-
-#include <iprt/file.h>
-#include <iprt/isofs.h>
-#include <iprt/list.h>
-#include <iprt/path.h>
-
-GuestTask::GuestTask(TaskType aTaskType, Guest *aThat, Progress *aProgress)
- : taskType(aTaskType),
- pGuest(aThat),
- pProgress(aProgress),
- rc(S_OK)
-{
-
-}
-
-GuestTask::~GuestTask()
-{
-
-}
-
-int GuestTask::startThread()
-{
- return RTThreadCreate(NULL, GuestTask::taskThread, this,
- 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
- "GuestTask");
-}
-
-/* static */
-DECLCALLBACK(int) GuestTask::taskThread(RTTHREAD /* aThread */, void *pvUser)
-{
- std::auto_ptr<GuestTask> task(static_cast<GuestTask*>(pvUser));
- AssertReturn(task.get(), VERR_GENERAL_FAILURE);
-
- ComObjPtr<Guest> pGuest = task->pGuest;
-
- LogFlowFuncEnter();
-
- HRESULT rc = S_OK;
-
- switch (task->taskType)
- {
-#ifdef VBOX_WITH_GUEST_CONTROL
- case TaskType_CopyFileToGuest:
- {
- rc = pGuest->taskCopyFileToGuest(task.get());
- break;
- }
- case TaskType_CopyFileFromGuest:
- {
- rc = pGuest->taskCopyFileFromGuest(task.get());
- break;
- }
- case TaskType_UpdateGuestAdditions:
- {
- rc = pGuest->taskUpdateGuestAdditions(task.get());
- break;
- }
-#endif
- default:
- AssertMsgFailed(("Invalid task type %u specified!\n", task->taskType));
- break;
- }
-
- LogFlowFunc(("rc=%Rhrc\n", rc));
- LogFlowFuncLeave();
-
- return VINF_SUCCESS;
-}
-
-/* static */
-int GuestTask::uploadProgress(unsigned uPercent, void *pvUser)
-{
- GuestTask *pTask = *(GuestTask**)pvUser;
-
- if ( pTask
- && !pTask->pProgress.isNull())
- {
- BOOL fCanceled;
- pTask->pProgress->COMGETTER(Canceled)(&fCanceled);
- if (fCanceled)
- return -1;
- pTask->pProgress->SetCurrentOperationProgress(uPercent);
- }
- return VINF_SUCCESS;
-}
-
-/* static */
-HRESULT GuestTask::setProgressSuccess(ComObjPtr<Progress> pProgress)
-{
- BOOL fCanceled;
- BOOL fCompleted;
- if ( SUCCEEDED(pProgress->COMGETTER(Canceled(&fCanceled)))
- && !fCanceled
- && SUCCEEDED(pProgress->COMGETTER(Completed(&fCompleted)))
- && !fCompleted)
- {
- return pProgress->notifyComplete(S_OK);
- }
-
- return S_OK;
-}
-
-/* static */
-HRESULT GuestTask::setProgressErrorMsg(HRESULT hr, ComObjPtr<Progress> pProgress,
- const char *pszText, ...)
-{
- BOOL fCanceled;
- BOOL fCompleted;
- if ( SUCCEEDED(pProgress->COMGETTER(Canceled(&fCanceled)))
- && !fCanceled
- && SUCCEEDED(pProgress->COMGETTER(Completed(&fCompleted)))
- && !fCompleted)
- {
- va_list va;
- va_start(va, pszText);
- HRESULT hr2 = pProgress->notifyCompleteV(hr,
- COM_IIDOF(IGuest),
- Guest::getStaticComponentName(),
- pszText,
- va);
- va_end(va);
- if (hr2 == S_OK) /* If unable to retrieve error, return input error. */
- hr2 = hr;
- return hr2;
- }
- return S_OK;
-}
-
-/* static */
-HRESULT GuestTask::setProgressErrorParent(HRESULT hr,
- ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest)
-{
- return setProgressErrorMsg(hr, pProgress,
- Utf8Str(com::ErrorInfo((IGuest*)pGuest, COM_IIDOF(IGuest)).getText()).c_str());
-}
-
-#ifdef VBOX_WITH_GUEST_CONTROL
-HRESULT Guest::taskCopyFileToGuest(GuestTask *aTask)
-{
- LogFlowFuncEnter();
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /*
- * Do *not* take a write lock here since we don't (and won't)
- * touch any class-specific data (of IGuest) here - only the member functions
- * which get called here can do that.
- */
-
- HRESULT rc = S_OK;
-
- try
- {
- ComObjPtr<Guest> pGuest = aTask->pGuest;
-
- /* Does our source file exist? */
- if (!RTFileExists(aTask->strSource.c_str()))
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Source file \"%s\" does not exist or is not a file"),
- aTask->strSource.c_str());
- }
- else
- {
- RTFILE fileSource;
- int vrc = RTFileOpen(&fileSource, aTask->strSource.c_str(),
- RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
- if (RT_FAILURE(vrc))
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Could not open source file \"%s\" for reading (%Rrc)"),
- aTask->strSource.c_str(), vrc);
- }
- else
- {
- uint64_t cbSize;
- vrc = RTFileGetSize(fileSource, &cbSize);
- if (RT_FAILURE(vrc))
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Could not query file size of \"%s\" (%Rrc)"),
- aTask->strSource.c_str(), vrc);
- }
- else
- {
- com::SafeArray<IN_BSTR> args;
- com::SafeArray<IN_BSTR> env;
-
- /*
- * Prepare tool command line.
- */
- char szOutput[RTPATH_MAX];
- size_t cchOutput = RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", aTask->strDest.c_str());
- if (cchOutput && cchOutput <= sizeof(szOutput) - 1)
- {
- /*
- * Normalize path slashes, based on the detected guest.
- */
- Utf8Str osType = mData.mOSTypeId;
- if ( osType.contains("Microsoft", Utf8Str::CaseInsensitive)
- || osType.contains("Windows", Utf8Str::CaseInsensitive))
- {
- /* We have a Windows guest. */
- RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */);
- }
- else /* ... or something which isn't from Redmond ... */
- {
- RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */);
- }
-
- args.push_back(Bstr(szOutput).raw()); /* We want to write a file ... */
- }
- else
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Destination file for source \"%s\" invalid (%ubytes)"),
- aTask->strSource.c_str(), cchOutput);
-
- ComPtr<IProgress> execProgress;
- ULONG uPID;
- if (SUCCEEDED(rc))
- {
- LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n",
- aTask->strSource.c_str(), aTask->strDest.c_str(), cbSize));
- /*
- * Okay, since we gathered all stuff we need until now to start the
- * actual copying, start the guest part now.
- */
- rc = pGuest->executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
- Bstr("Copying file to guest").raw(),
- ComSafeArrayAsInParam(args),
- ComSafeArrayAsInParam(env),
- Bstr(aTask->strUserName).raw(),
- Bstr(aTask->strPassword).raw(),
- ExecuteProcessFlag_WaitForProcessStartOnly,
- NULL, NULL,
- execProgress.asOutParam(), &uPID);
- if (FAILED(rc))
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
- }
-
- if (SUCCEEDED(rc))
- {
- BOOL fCompleted = FALSE;
- BOOL fCanceled = FALSE;
-
- uint64_t cbTransferedTotal = 0;
- uint64_t cbToRead = cbSize;
-
- SafeArray<BYTE> aInputData(_64K);
- while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
- && !fCompleted)
- {
- size_t cbRead = 0;
- if (cbSize) /* If we have nothing to read, take a shortcut. */
- {
- /** @todo Not very efficient, but works for now. */
- vrc = RTFileSeek(fileSource, cbTransferedTotal,
- RTFILE_SEEK_BEGIN, NULL /* poffActual */);
- if (RT_SUCCESS(vrc))
- {
- vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(),
- RT_MIN(cbToRead, _64K), &cbRead);
- /*
- * Some other error occured? There might be a chance that RTFileRead
- * could not resolve/map the native error code to an IPRT code, so just
- * print a generic error.
- */
- if (RT_FAILURE(vrc))
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Could not read from file \"%s\" (%Rrc)"),
- aTask->strSource.c_str(), vrc);
- break;
- }
- }
- else
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Seeking file \"%s\" failed; offset = %RU64 (%Rrc)"),
- aTask->strSource.c_str(), cbTransferedTotal, vrc);
- break;
- }
- }
- /* Resize buffer to reflect amount we just have read.
- * Size 0 is allowed! */
- aInputData.resize(cbRead);
-
- ULONG uFlags = ProcessInputFlag_None;
- /* Did we reach the end of the content we want to transfer (last chunk)? */
- if ( (cbRead < _64K)
- /* Did we reach the last block which is exactly _64K? */
- || (cbToRead - cbRead == 0)
- /* ... or does the user want to cancel? */
- || ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled)))
- && fCanceled)
- )
- {
- uFlags |= ProcessInputFlag_EndOfFile;
- }
-
- ULONG cbBytesWritten = 0;
- rc = pGuest->SetProcessInput(uPID, uFlags,
- 0 /* Infinite timeout */,
- ComSafeArrayAsInParam(aInputData), &cbBytesWritten);
- if (FAILED(rc))
- {
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
- break;
- }
-
- Assert(cbRead <= cbToRead);
- Assert(cbToRead >= cbRead);
- /* Only subtract bytes reported written by the guest. */
- cbToRead -= cbBytesWritten;
-
- cbTransferedTotal += cbBytesWritten;
- Assert(cbTransferedTotal <= cbSize);
- aTask->pProgress->SetCurrentOperationProgress((ULONG)(cbTransferedTotal / (cbSize / 100.0)));
-
- /* End of file reached? */
- if (cbToRead == 0)
- break;
-
- /* Did the user cancel the operation above? */
- if (fCanceled)
- break;
-
- /* Progress canceled by Main API? */
- if ( SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled)))
- && fCanceled)
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Copy operation of file \"%s\" was canceled on guest side"),
- aTask->strSource.c_str());
- break;
- }
- }
-
- if (SUCCEEDED(rc))
- {
- /*
- * If we got here this means the started process either was completed,
- * canceled or we simply got all stuff transferred.
- */
- rc = executeWaitForExit(uPID, execProgress, 0 /* No timeout */);
- if (FAILED(rc))
- {
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
- }
- else
- {
- VBOXGUESTCTRL_PROCESS proc;
- vrc = processGetStatus(uPID, &proc, true /* Remove from PID list. */);
- if (RT_SUCCESS(vrc))
- {
-
- if ( proc.mExitCode != 0
- || proc.mStatus != ExecuteProcessStatus_TerminatedNormally)
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Guest process reported error %u (status: %u) while copying file \"%s\" to \"%s\""),
- proc.mExitCode, proc.mStatus, aTask->strSource.c_str(), aTask->strDest.c_str());
- }
- }
- }
- }
-
- if (SUCCEEDED(rc))
- {
- if (fCanceled)
- {
- /*
- * In order to make the progress object to behave nicely, we also have to
- * notify the object with a complete event when it's canceled.
- */
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Copying file \"%s\" to guest canceled"),
- aTask->strSource.c_str());
- }
- else
- {
- /*
- * Even if we succeeded until here make sure to check whether we really transfered
- * everything.
- */
- if ( cbSize > 0
- && cbTransferedTotal == 0)
- {
- /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
- * to the destination -> access denied. */
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Access denied when copying file \"%s\" to \"%s\""),
- aTask->strSource.c_str(), aTask->strDest.c_str());
- }
- else if (cbTransferedTotal < cbSize)
- {
- /* If we did not copy all let the user know. */
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Copying file \"%s\" failed (%u/%u bytes transfered)"),
- aTask->strSource.c_str(), cbTransferedTotal, cbSize);
- }
- else /* Yay, all went fine! */
- rc = GuestTask::setProgressSuccess(aTask->pProgress);
- }
- }
- }
- }
- RTFileClose(fileSource);
- }
- }
- }
- catch (HRESULT aRC)
- {
- rc = aRC;
- }
-
- /* Clean up */
- aTask->rc = rc;
-
- LogFlowFunc(("rc=%Rhrc\n", rc));
- LogFlowFuncLeave();
-
- return VINF_SUCCESS;
-}
-
-HRESULT Guest::taskCopyFileFromGuest(GuestTask *aTask)
-{
- LogFlowFuncEnter();
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /*
- * Do *not* take a write lock here since we don't (and won't)
- * touch any class-specific data (of IGuest) here - only the member functions
- * which get called here can do that.
- */
-
- HRESULT rc = S_OK;
-
- try
- {
- ComObjPtr<Guest> pGuest = aTask->pGuest;
-
- /* Does our source file exist? */
- BOOL fFileExists;
- rc = pGuest->FileExists(Bstr(aTask->strSource).raw(),
- Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(),
- &fFileExists);
- if (SUCCEEDED(rc))
- {
- if (!fFileExists)
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Source file \"%s\" does not exist, or is not a file"),
- aTask->strSource.c_str());
- }
- else
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
-
- /* Query file size to make an estimate for our progress object. */
- if (SUCCEEDED(rc))
- {
- LONG64 lFileSize;
- rc = pGuest->FileQuerySize(Bstr(aTask->strSource).raw(),
- Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(),
- &lFileSize);
- if (FAILED(rc))
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
-
- com::SafeArray<IN_BSTR> args;
- com::SafeArray<IN_BSTR> env;
-
- if (SUCCEEDED(rc))
- {
- /*
- * Prepare tool command line.
- */
- char szSource[RTPATH_MAX];
- size_t cchSource = RTStrPrintf(szSource, sizeof(szSource), "%s", aTask->strSource.c_str());
- if (cchSource && cchSource <= sizeof(szSource) - 1)
- {
- /*
- * Normalize path slashes, based on the detected guest.
- */
- Utf8Str osType = mData.mOSTypeId;
- if ( osType.contains("Microsoft", Utf8Str::CaseInsensitive)
- || osType.contains("Windows", Utf8Str::CaseInsensitive))
- {
- /* We have a Windows guest. */
- RTPathChangeToDosSlashes(szSource, true /* Force conversion. */);
- }
- else /* ... or something which isn't from Redmond ... */
- {
- RTPathChangeToUnixSlashes(szSource, true /* Force conversion. */);
- }
-
- args.push_back(Bstr(szSource).raw()); /* Tell our cat tool which file to output. */
- }
- else
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Source file \"%s\" too long (%ubytes)"),
- aTask->strSource.c_str(), cchSource);
- }
-
- ComPtr<IProgress> execProgress;
- ULONG uPID;
- if (SUCCEEDED(rc))
- {
- LogRel(("Copying file \"%s\" to host \"%s\" (%u bytes) ...\n",
- aTask->strSource.c_str(), aTask->strDest.c_str(), lFileSize));
-
- /*
- * Okay, since we gathered all stuff we need until now to start the
- * actual copying, start the guest part now.
- */
- rc = pGuest->executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
- Bstr("Copying file to host").raw(),
- ComSafeArrayAsInParam(args),
- ComSafeArrayAsInParam(env),
- Bstr(aTask->strUserName).raw(),
- Bstr(aTask->strPassword).raw(),
- ExecuteProcessFlag_WaitForProcessStartOnly
- | ExecuteProcessFlag_WaitForStdOut,
- NULL, NULL,
- execProgress.asOutParam(), &uPID);
- if (FAILED(rc))
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
- }
-
- if (SUCCEEDED(rc))
- {
- BOOL fCompleted = FALSE;
- BOOL fCanceled = FALSE;
-
- RTFILE hFileDest;
- int vrc = RTFileOpen(&hFileDest, aTask->strDest.c_str(),
- RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE);
- if (RT_FAILURE(vrc))
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Unable to create/open destination file \"%s\", rc=%Rrc"),
- aTask->strDest.c_str(), vrc);
- else
- {
- size_t cbToRead = lFileSize;
- size_t cbTransfered = 0;
- while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
- && !fCompleted)
- {
- SafeArray<BYTE> aOutputData;
- rc = pGuest->GetProcessOutput(uPID, ProcessOutputFlag_None /* StdOut */,
- 0 /* No timeout. */,
- _64K, ComSafeArrayAsOutParam(aOutputData));
- if (SUCCEEDED(rc))
- {
- if (aOutputData.size())
- {
- vrc = RTFileWrite(hFileDest, aOutputData.raw(), aOutputData.size(), NULL /* No partial writes */);
- if (RT_FAILURE(vrc))
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Error writing to file \"%s\" (%u bytes left), rc=%Rrc"),
- aTask->strSource.c_str(), cbToRead, vrc);
- break;
- }
-
- Assert(cbToRead >= aOutputData.size());
- cbToRead -= aOutputData.size();
- cbTransfered += aOutputData.size();
-
- aTask->pProgress->SetCurrentOperationProgress(cbTransfered / (lFileSize / 100.0));
- }
-
- /* Nothing read this time; try next round. */
- }
- else
- {
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
- break;
- }
- }
-
- RTFileClose(hFileDest);
-
- if (SUCCEEDED(rc))
- {
- if ( cbTransfered
- && (cbTransfered != lFileSize))
- {
- /*
- * Only bitch about an unexpected end of a file when there already
- * was data read from that file. If this was the very first read we can
- * be (almost) sure that this file is not meant to be read by the specified user.
- */
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Unexpected end of file \"%s\" (%u bytes total, %u bytes transferred)"),
- aTask->strSource.c_str(), lFileSize, cbTransfered);
- }
-
- if (SUCCEEDED(rc))
- rc = GuestTask::setProgressSuccess(aTask->pProgress);
- }
- }
- }
- }
- }
- catch (HRESULT aRC)
- {
- rc = aRC;
- }
-
- /* Clean up */
- aTask->rc = rc;
-
- LogFlowFunc(("rc=%Rhrc\n", rc));
- LogFlowFuncLeave();
-
- return VINF_SUCCESS;
-}
-
-HRESULT Guest::taskUpdateGuestAdditions(GuestTask *aTask)
-{
- LogFlowFuncEnter();
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /*
- * Do *not* take a write lock here since we don't (and won't)
- * touch any class-specific data (of IGuest) here - only the member functions
- * which get called here can do that.
- */
-
- HRESULT rc = S_OK;
- BOOL fCompleted;
- BOOL fCanceled;
-
- try
- {
- ComObjPtr<Guest> pGuest = aTask->pGuest;
-
- aTask->pProgress->SetCurrentOperationProgress(10);
-
- /*
- * Determine guest OS type and the required installer image.
- * At the moment only Windows guests are supported.
- */
- Utf8Str installerImage;
- Bstr osTypeId;
- if ( SUCCEEDED(pGuest->COMGETTER(OSTypeId(osTypeId.asOutParam())))
- && !osTypeId.isEmpty())
- {
- Utf8Str osTypeIdUtf8(osTypeId); /* Needed for .contains(). */
- if ( osTypeIdUtf8.contains("Microsoft", Utf8Str::CaseInsensitive)
- || osTypeIdUtf8.contains("Windows", Utf8Str::CaseInsensitive))
- {
- if (osTypeIdUtf8.contains("64", Utf8Str::CaseInsensitive))
- installerImage = "VBOXWINDOWSADDITIONS_AMD64.EXE";
- else
- installerImage = "VBOXWINDOWSADDITIONS_X86.EXE";
- /* Since the installers are located in the root directory,
- * no further path processing needs to be done (yet). */
- }
- else /* Everything else is not supported (yet). */
- throw GuestTask::setProgressErrorMsg(VBOX_E_NOT_SUPPORTED, aTask->pProgress,
- Guest::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"),
- osTypeIdUtf8.c_str());
- }
- else
- throw GuestTask::setProgressErrorMsg(VBOX_E_NOT_SUPPORTED, aTask->pProgress,
- Guest::tr("Could not detected guest OS type/version, please update manually"));
- Assert(!installerImage.isEmpty());
-
- /*
- * Try to open the .ISO file and locate the specified installer.
- */
- RTISOFSFILE iso;
- int vrc = RTIsoFsOpen(&iso, aTask->strSource.c_str());
- if (RT_FAILURE(vrc))
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_FILE_ERROR, aTask->pProgress,
- Guest::tr("Invalid installation medium detected: \"%s\""),
- aTask->strSource.c_str());
- }
- else
- {
- uint32_t cbOffset;
- size_t cbLength;
- vrc = RTIsoFsGetFileInfo(&iso, installerImage.c_str(), &cbOffset, &cbLength);
- if ( RT_SUCCESS(vrc)
- && cbOffset
- && cbLength)
- {
- vrc = RTFileSeek(iso.file, cbOffset, RTFILE_SEEK_BEGIN, NULL);
- if (RT_FAILURE(vrc))
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Could not seek to setup file on installation medium \"%s\" (%Rrc)"),
- aTask->strSource.c_str(), vrc);
- }
- else
- {
- switch (vrc)
- {
- case VERR_FILE_NOT_FOUND:
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Setup file was not found on installation medium \"%s\""),
- aTask->strSource.c_str());
- break;
-
- default:
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("An unknown error (%Rrc) occured while retrieving information of setup file on installation medium \"%s\""),
- vrc, aTask->strSource.c_str());
- break;
- }
- }
-
- /* Specify the ouput path on the guest side. */
- Utf8Str strInstallerPath = "%TEMP%\\VBoxWindowsAdditions.exe";
-
- if (RT_SUCCESS(vrc))
- {
- /* Okay, we're ready to start our copy routine on the guest! */
- aTask->pProgress->SetCurrentOperationProgress(15);
-
- /* Prepare command line args. */
- com::SafeArray<IN_BSTR> args;
- com::SafeArray<IN_BSTR> env;
-
- args.push_back(Bstr("--output").raw()); /* We want to write a file ... */
- args.push_back(Bstr(strInstallerPath.c_str()).raw()); /* ... with this path. */
-
- if (SUCCEEDED(rc))
- {
- ComPtr<IProgress> progressCat;
- ULONG uPID;
-
- /*
- * Start built-in "vbox_cat" tool (inside VBoxService) to
- * copy over/pipe the data into a file on the guest (with
- * system rights, no username/password specified).
- */
- rc = pGuest->executeProcessInternal(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
- ExecuteProcessFlag_Hidden
- | ExecuteProcessFlag_WaitForProcessStartOnly,
- ComSafeArrayAsInParam(args),
- ComSafeArrayAsInParam(env),
- Bstr("").raw() /* Username. */,
- Bstr("").raw() /* Password */,
- 5 * 1000 /* Wait 5s for getting the process started. */,
- &uPID, progressCat.asOutParam(), &vrc);
- if (FAILED(rc))
- {
- /* Errors which return VBOX_E_NOT_SUPPORTED can be safely skipped by the caller
- * to silently fall back to "normal" (old) .ISO mounting. */
-
- /* Due to a very limited COM error range we use vrc for a more detailed error
- * lookup to figure out what went wrong. */
- switch (vrc)
- {
- /* Guest execution service is not (yet) ready. This basically means that either VBoxService
- * is not running (yet) or that the Guest Additions are too old (because VBoxService does not
- * support the guest execution feature in this version). */
- case VERR_NOT_FOUND:
- LogRel(("Guest Additions seem not to be installed yet\n"));
- rc = GuestTask::setProgressErrorMsg(VBOX_E_NOT_SUPPORTED, aTask->pProgress,
- Guest::tr("Guest Additions seem not to be installed or are not ready to update yet"));
- break;
-
- /* Getting back a VERR_INVALID_PARAMETER indicates that the installed Guest Additions are supporting the guest
- * execution but not the built-in "vbox_cat" tool of VBoxService (< 4.0). */
- case VERR_INVALID_PARAMETER:
- LogRel(("Guest Additions are installed but don't supported automatic updating\n"));
- rc = GuestTask::setProgressErrorMsg(VBOX_E_NOT_SUPPORTED, aTask->pProgress,
- Guest::tr("Installed Guest Additions do not support automatic updating"));
- break;
-
- case VERR_TIMEOUT:
- LogRel(("Guest was unable to start copying the Guest Additions setup within time\n"));
- rc = GuestTask::setProgressErrorMsg(E_FAIL, aTask->pProgress,
- Guest::tr("Guest was unable to start copying the Guest Additions setup within time"));
- break;
-
- default:
- rc = GuestTask::setProgressErrorMsg(E_FAIL, aTask->pProgress,
- Guest::tr("Error copying Guest Additions setup file to guest path \"%s\" (%Rrc)"),
- strInstallerPath.c_str(), vrc);
- break;
- }
- }
- else
- {
- LogRel(("Automatic update of Guest Additions started, using \"%s\"\n", aTask->strSource.c_str()));
- LogRel(("Copying Guest Additions installer \"%s\" to \"%s\" on guest ...\n",
- installerImage.c_str(), strInstallerPath.c_str()));
- aTask->pProgress->SetCurrentOperationProgress(20);
-
- /* Wait for process to exit ... */
- SafeArray<BYTE> aInputData(_64K);
- while ( SUCCEEDED(progressCat->COMGETTER(Completed(&fCompleted)))
- && !fCompleted)
- {
- size_t cbRead;
- /* cbLength contains remaining bytes of our installer file
- * opened above to read. */
- size_t cbToRead = RT_MIN(cbLength, _64K);
- if (cbToRead)
- {
- vrc = RTFileRead(iso.file, (uint8_t*)aInputData.raw(), cbToRead, &cbRead);
- if ( cbRead
- && RT_SUCCESS(vrc))
- {
- /* Resize buffer to reflect amount we just have read. */
- if (cbRead > 0)
- aInputData.resize(cbRead);
-
- /* Did we reach the end of the content we want to transfer (last chunk)? */
- ULONG uFlags = ProcessInputFlag_None;
- if ( (cbRead < _64K)
- /* Did we reach the last block which is exactly _64K? */
- || (cbToRead - cbRead == 0)
- /* ... or does the user want to cancel? */
- || ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled)))
- && fCanceled)
- )
- {
- uFlags |= ProcessInputFlag_EndOfFile;
- }
-
- /* Transfer the current chunk ... */
- #ifdef DEBUG_andy
- LogRel(("Copying Guest Additions (%u bytes left) ...\n", cbLength));
- #endif
- ULONG uBytesWritten;
- rc = pGuest->SetProcessInput(uPID, uFlags,
- 10 * 1000 /* Wait 10s for getting the input data transfered. */,
- ComSafeArrayAsInParam(aInputData), &uBytesWritten);
- if (FAILED(rc))
- {
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
- break;
- }
-
- /* If task was canceled above also cancel the process execution. */
- if (fCanceled)
- progressCat->Cancel();
-
- #ifdef DEBUG_andy
- LogRel(("Copying Guest Additions (%u bytes written) ...\n", uBytesWritten));
- #endif
- Assert(cbLength >= uBytesWritten);
- cbLength -= uBytesWritten;
- }
- else if (RT_FAILURE(vrc))
- {
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Error while reading setup file \"%s\" (To read: %u, Size: %u) from installation medium (%Rrc)"),
- installerImage.c_str(), cbToRead, cbLength, vrc);
- }
- }
-
- /* Internal progress canceled? */
- if ( SUCCEEDED(progressCat->COMGETTER(Canceled(&fCanceled)))
- && fCanceled)
- {
- aTask->pProgress->Cancel();
- break;
- }
- }
- }
- }
- }
- RTIsoFsClose(&iso);
-
- if ( SUCCEEDED(rc)
- && ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled)))
- && !fCanceled
- )
- )
- {
- /*
- * Installer was transferred successfully, so let's start it
- * (with system rights).
- */
- LogRel(("Preparing to execute Guest Additions update ...\n"));
- aTask->pProgress->SetCurrentOperationProgress(66);
-
- /* Prepare command line args for installer. */
- com::SafeArray<IN_BSTR> installerArgs;
- com::SafeArray<IN_BSTR> installerEnv;
-
- /** @todo Only Windows! */
- installerArgs.push_back(Bstr(strInstallerPath).raw()); /* The actual (internal) installer image (as argv[0]). */
- /* Note that starting at Windows Vista the lovely session 0 separation applies:
- * This means that if we run an application with the profile/security context
- * of VBoxService (system rights!) we're not able to show any UI. */
- installerArgs.push_back(Bstr("/S").raw()); /* We want to install in silent mode. */
- installerArgs.push_back(Bstr("/l").raw()); /* ... and logging enabled. */
- /* Don't quit VBoxService during upgrade because it still is used for this
- * piece of code we're in right now (that is, here!) ... */
- installerArgs.push_back(Bstr("/no_vboxservice_exit").raw());
- /* Tell the installer to report its current installation status
- * using a running VBoxTray instance via balloon messages in the
- * Windows taskbar. */
- installerArgs.push_back(Bstr("/post_installstatus").raw());
-
- /*
- * Start the just copied over installer with system rights
- * in silent mode on the guest. Don't use the hidden flag since there
- * may be pop ups the user has to process.
- */
- ComPtr<IProgress> progressInstaller;
- ULONG uPID;
- rc = pGuest->executeProcessInternal(Bstr(strInstallerPath).raw(),
- ExecuteProcessFlag_WaitForProcessStartOnly,
- ComSafeArrayAsInParam(installerArgs),
- ComSafeArrayAsInParam(installerEnv),
- Bstr("").raw() /* Username */,
- Bstr("").raw() /* Password */,
- 10 * 1000 /* Wait 10s for getting the process started */,
- &uPID, progressInstaller.asOutParam(), &vrc);
- if (SUCCEEDED(rc))
- {
- LogRel(("Guest Additions update is running ...\n"));
-
- /* If the caller does not want to wait for out guest update process to end,
- * complete the progress object now so that the caller can do other work. */
- if (aTask->uFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly)
- {
- rc = GuestTask::setProgressSuccess(aTask->pProgress);
- AssertComRC(rc);
- }
- else
- aTask->pProgress->SetCurrentOperationProgress(70);
-
- /* Wait until the Guest Additions installer finishes ... */
- while ( SUCCEEDED(progressInstaller->COMGETTER(Completed(&fCompleted)))
- && !fCompleted)
- {
- if ( SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled)))
- && fCanceled)
- {
- progressInstaller->Cancel();
- break;
- }
- /* Progress canceled by Main API? */
- if ( SUCCEEDED(progressInstaller->COMGETTER(Canceled(&fCanceled)))
- && fCanceled)
- {
- break;
- }
- RTThreadSleep(100);
- }
-
- ExecuteProcessStatus_T retStatus;
- ULONG uRetExitCode, uRetFlags;
- rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus);
- if (SUCCEEDED(rc))
- {
- if (fCompleted)
- {
- if (uRetExitCode == 0)
- {
- LogRel(("Guest Additions update successful!\n"));
- if ( SUCCEEDED(aTask->pProgress->COMGETTER(Completed(&fCompleted)))
- && !fCompleted)
- {
- rc = GuestTask::setProgressSuccess(aTask->pProgress);
- }
- }
- else
- {
- LogRel(("Guest Additions update failed (Exit code=%u, Status=%u, Flags=%u)\n",
- uRetExitCode, retStatus, uRetFlags));
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Guest Additions update failed with exit code=%u (status=%u, flags=%u)"),
- uRetExitCode, retStatus, uRetFlags);
- }
- }
- else if ( SUCCEEDED(progressInstaller->COMGETTER(Canceled(&fCanceled)))
- && fCanceled)
- {
- LogRel(("Guest Additions update was canceled\n"));
- rc = GuestTask::setProgressErrorMsg(VBOX_E_IPRT_ERROR, aTask->pProgress,
- Guest::tr("Guest Additions update was canceled by the guest with exit code=%u (status=%u, flags=%u)"),
- uRetExitCode, retStatus, uRetFlags);
- }
- else
- {
- LogRel(("Guest Additions update was canceled by the user\n"));
- }
- }
- else
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
- }
- else
- rc = GuestTask::setProgressErrorParent(rc, aTask->pProgress, pGuest);
- }
- }
- }
- catch (HRESULT aRC)
- {
- rc = aRC;
- }
-
- /* Clean up */
- aTask->rc = rc;
-
- LogFlowFunc(("rc=%Rhrc\n", rc));
- LogFlowFuncLeave();
-
- return VINF_SUCCESS;
-}
-#endif
-
diff --git a/src/VBox/Main/src-client/GuestCtrlPrivate.cpp b/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
new file mode 100644
index 000000000..1a504aa41
--- /dev/null
+++ b/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
@@ -0,0 +1,1077 @@
+/* $Id: GuestCtrlPrivate.cpp $ */
+/** @file
+ *
+ * Internal helpers/structures for guest control functionality.
+ */
+
+/*
+ * Copyright (C) 2011-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/******************************************************************************
+ * Header Files *
+ ******************************************************************************/
+#include "GuestCtrlImplPrivate.h"
+
+#include <iprt/asm.h>
+#include <iprt/ctype.h>
+#ifdef DEBUG
+# include <iprt/file.h>
+#endif /* DEBUG */
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
+#include <VBox/log.h>
+
+/******************************************************************************
+ * Structures and Typedefs *
+ ******************************************************************************/
+
+GuestCtrlEvent::GuestCtrlEvent(void)
+ : fCanceled(false),
+ fCompleted(false),
+ hEventSem(NIL_RTSEMEVENT),
+ mRC(VINF_SUCCESS)
+{
+}
+
+GuestCtrlEvent::~GuestCtrlEvent(void)
+{
+ Destroy();
+}
+
+int GuestCtrlEvent::Cancel(void)
+{
+ int rc = VINF_SUCCESS;
+ if (!ASMAtomicReadBool(&fCompleted))
+ {
+ if (!ASMAtomicReadBool(&fCanceled))
+ {
+ ASMAtomicXchgBool(&fCanceled, true);
+
+ LogFlowThisFunc(("Cancelling event ...\n"));
+ rc = hEventSem != NIL_RTSEMEVENT
+ ? RTSemEventSignal(hEventSem) : VINF_SUCCESS;
+ }
+ }
+
+ return rc;
+}
+
+bool GuestCtrlEvent::Canceled(void)
+{
+ return ASMAtomicReadBool(&fCanceled);
+}
+
+void GuestCtrlEvent::Destroy(void)
+{
+ int rc = Cancel();
+ AssertRC(rc);
+
+ if (hEventSem != NIL_RTSEMEVENT)
+ {
+ RTSemEventDestroy(hEventSem);
+ hEventSem = NIL_RTSEMEVENT;
+ }
+}
+
+int GuestCtrlEvent::Init(void)
+{
+ return RTSemEventCreate(&hEventSem);
+}
+
+int GuestCtrlEvent::Signal(int rc /*= VINF_SUCCESS*/)
+{
+ AssertReturn(hEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
+
+ mRC = rc;
+
+ return RTSemEventSignal(hEventSem);
+}
+
+int GuestCtrlEvent::Wait(ULONG uTimeoutMS)
+{
+ LogFlowThisFuncEnter();
+
+ AssertReturn(hEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
+
+ RTMSINTERVAL msInterval = uTimeoutMS;
+ if (!uTimeoutMS)
+ msInterval = RT_INDEFINITE_WAIT;
+ int rc = RTSemEventWait(hEventSem, msInterval);
+ if (RT_SUCCESS(rc))
+ ASMAtomicWriteBool(&fCompleted, true);
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GuestCtrlCallback::GuestCtrlCallback(void)
+ : pvData(NULL),
+ cbData(0),
+ mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN),
+ uFlags(0),
+ pvPayload(NULL),
+ cbPayload(0)
+{
+}
+
+GuestCtrlCallback::GuestCtrlCallback(eVBoxGuestCtrlCallbackType enmType)
+ : pvData(NULL),
+ cbData(0),
+ mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN),
+ uFlags(0),
+ pvPayload(NULL),
+ cbPayload(0)
+{
+ int rc = Init(enmType);
+ AssertRC(rc);
+}
+
+GuestCtrlCallback::~GuestCtrlCallback(void)
+{
+ Destroy();
+}
+
+int GuestCtrlCallback::Init(eVBoxGuestCtrlCallbackType enmType)
+{
+ AssertReturn(enmType > VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN, VERR_INVALID_PARAMETER);
+ Assert((pvData == NULL) && !cbData);
+
+ switch (enmType)
+ {
+ case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START:
+ {
+ pvData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS));
+ AssertPtrReturn(pvData, VERR_NO_MEMORY);
+ RT_BZERO(pvData, sizeof(CALLBACKDATAEXECSTATUS));
+ cbData = sizeof(CALLBACKDATAEXECSTATUS);
+ break;
+ }
+
+ case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT:
+ {
+ pvData = (PCALLBACKDATAEXECOUT)RTMemAlloc(sizeof(CALLBACKDATAEXECOUT));
+ AssertPtrReturn(pvData, VERR_NO_MEMORY);
+ RT_BZERO(pvData, sizeof(CALLBACKDATAEXECOUT));
+ cbData = sizeof(CALLBACKDATAEXECOUT);
+ break;
+ }
+
+ case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS:
+ {
+ pvData = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECINSTATUS));
+ AssertPtrReturn(pvData, VERR_NO_MEMORY);
+ RT_BZERO(pvData, sizeof(CALLBACKDATAEXECINSTATUS));
+ cbData = sizeof(CALLBACKDATAEXECINSTATUS);
+ break;
+ }
+
+ default:
+ AssertMsgFailed(("Unknown callback type specified (%d)\n", enmType));
+ break;
+ }
+
+ int rc = GuestCtrlEvent::Init();
+ if (RT_SUCCESS(rc))
+ mType = enmType;
+
+ return rc;
+}
+
+void GuestCtrlCallback::Destroy(void)
+{
+ GuestCtrlEvent::Destroy();
+
+ switch (mType)
+ {
+ case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT:
+ {
+ PCALLBACKDATAEXECOUT pThis = (PCALLBACKDATAEXECOUT)pvData;
+ AssertPtr(pThis);
+ if (pThis->pvData)
+ RTMemFree(pThis->pvData);
+ }
+
+ default:
+ break;
+ }
+
+ mType = VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN;
+ if (pvData)
+ {
+ RTMemFree(pvData);
+ pvData = NULL;
+ }
+ cbData = 0;
+
+ if (pvPayload)
+ {
+ RTMemFree(pvPayload);
+ pvPayload = NULL;
+ }
+ cbPayload = 0;
+}
+
+int GuestCtrlCallback::SetData(const void *pvCallback, size_t cbCallback)
+{
+ if (!cbCallback)
+ return VINF_SUCCESS;
+ AssertPtr(pvCallback);
+
+ switch (mType)
+ {
+ case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START:
+ {
+ PCALLBACKDATAEXECSTATUS pThis = (PCALLBACKDATAEXECSTATUS)pvData;
+ PCALLBACKDATAEXECSTATUS pCB = (PCALLBACKDATAEXECSTATUS)pvCallback;
+ Assert(cbCallback == sizeof(CALLBACKDATAEXECSTATUS));
+
+ pThis->u32Flags = pCB->u32Flags;
+ pThis->u32PID = pCB->u32PID;
+ pThis->u32Status = pCB->u32Status;
+ break;
+ }
+
+ case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT:
+ {
+ PCALLBACKDATAEXECOUT pThis = (PCALLBACKDATAEXECOUT)pvData;
+ PCALLBACKDATAEXECOUT pCB = (PCALLBACKDATAEXECOUT)pvCallback;
+ Assert(cbCallback == sizeof(CALLBACKDATAEXECOUT));
+
+ pThis->cbData = pCB->cbData;
+ if (pThis->cbData)
+ {
+ pThis->pvData = RTMemAlloc(pCB->cbData);
+ AssertPtrReturn(pThis->pvData, VERR_NO_MEMORY);
+ memcpy(pThis->pvData, pCB->pvData, pCB->cbData);
+ }
+ pThis->u32Flags = pCB->u32Flags;
+ pThis->u32PID = pCB->u32PID;
+ break;
+ }
+
+ case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS:
+ {
+ PCALLBACKDATAEXECINSTATUS pThis = (PCALLBACKDATAEXECINSTATUS)pvData;
+ PCALLBACKDATAEXECINSTATUS pCB = (PCALLBACKDATAEXECINSTATUS)pvCallback;
+ Assert(cbCallback == sizeof(CALLBACKDATAEXECINSTATUS));
+
+ pThis->cbProcessed = pCB->cbProcessed;
+ pThis->u32Flags = pCB->u32Flags;
+ pThis->u32PID = pCB->u32PID;
+ pThis->u32Status = pCB->u32Status;
+ break;
+ }
+
+ default:
+ AssertMsgFailed(("Callback type not handled (%d)\n", mType));
+ break;
+ }
+
+ return VINF_SUCCESS;
+}
+
+int GuestCtrlCallback::SetPayload(const void *pvToWrite, size_t cbToWrite)
+{
+ if (!cbToWrite)
+ return VINF_SUCCESS;
+ AssertPtr(pvToWrite);
+
+ Assert(pvPayload == NULL); /* Can't reuse callbacks! */
+ pvPayload = RTMemAlloc(cbToWrite);
+ if (!pvPayload)
+ return VERR_NO_MEMORY;
+
+ memcpy(pvPayload, pvToWrite, cbToWrite);
+ cbPayload = cbToWrite;
+
+ return VINF_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GuestProcessWaitEvent::GuestProcessWaitEvent(void)
+ : mFlags(0),
+ mResult(ProcessWaitResult_None)
+{
+}
+
+GuestProcessWaitEvent::GuestProcessWaitEvent(uint32_t uWaitFlags)
+ : mFlags(uWaitFlags)
+{
+ int rc = GuestCtrlEvent::Init();
+ AssertRC(rc);
+}
+
+GuestProcessWaitEvent::~GuestProcessWaitEvent(void)
+{
+ Destroy();
+}
+
+void GuestProcessWaitEvent::Destroy(void)
+{
+ GuestCtrlEvent::Destroy();
+
+ mFlags = ProcessWaitForFlag_None;
+}
+
+int GuestProcessWaitEvent::Signal(ProcessWaitResult_T enmResult, int rc /*= VINF_SUCCESS*/)
+{
+ mResult = enmResult;
+
+ return GuestCtrlEvent::Signal(rc);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int GuestEnvironment::BuildEnvironmentBlock(void **ppvEnv, size_t *pcbEnv, uint32_t *pcEnvVars)
+{
+ AssertPtrReturn(ppvEnv, VERR_INVALID_POINTER);
+ /* Rest is optional. */
+
+ size_t cbEnv = 0;
+ uint32_t cEnvVars = 0;
+
+ int rc = VINF_SUCCESS;
+
+ size_t cEnv = mEnvironment.size();
+ if (cEnv)
+ {
+ std::map<Utf8Str, Utf8Str>::const_iterator itEnv = mEnvironment.begin();
+ for (; itEnv != mEnvironment.end() && RT_SUCCESS(rc); itEnv++)
+ {
+ char *pszEnv;
+ if (!RTStrAPrintf(&pszEnv, "%s=%s", itEnv->first.c_str(), itEnv->second.c_str()))
+ {
+ rc = VERR_NO_MEMORY;
+ break;
+ }
+ AssertPtr(pszEnv);
+ rc = appendToEnvBlock(pszEnv, ppvEnv, &cbEnv, &cEnvVars);
+ RTStrFree(pszEnv);
+ }
+ Assert(cEnv == cEnvVars);
+ }
+
+ if (pcbEnv)
+ *pcbEnv = cbEnv;
+ if (pcEnvVars)
+ *pcEnvVars = cEnvVars;
+
+ return rc;
+}
+
+void GuestEnvironment::Clear(void)
+{
+ mEnvironment.clear();
+}
+
+int GuestEnvironment::CopyFrom(const GuestEnvironmentArray &environment)
+{
+ int rc = VINF_SUCCESS;
+
+ for (GuestEnvironmentArray::const_iterator it = environment.begin();
+ it != environment.end() && RT_SUCCESS(rc);
+ ++it)
+ {
+ rc = Set((*it));
+ }
+
+ return rc;
+}
+
+int GuestEnvironment::CopyTo(GuestEnvironmentArray &environment)
+{
+ size_t s = 0;
+ for (std::map<Utf8Str, Utf8Str>::const_iterator it = mEnvironment.begin();
+ it != mEnvironment.end();
+ ++it, ++s)
+ {
+ environment[s] = Bstr(it->first + "=" + it->second).raw();
+ }
+
+ return VINF_SUCCESS;
+}
+
+/* static */
+void GuestEnvironment::FreeEnvironmentBlock(void *pvEnv)
+{
+ if (pvEnv)
+ RTMemFree(pvEnv);
+}
+
+Utf8Str GuestEnvironment::Get(size_t nPos)
+{
+ size_t curPos = 0;
+ std::map<Utf8Str, Utf8Str>::const_iterator it = mEnvironment.begin();
+ for (; it != mEnvironment.end() && curPos < nPos;
+ ++it, ++curPos) { }
+
+ if (it != mEnvironment.end())
+ return Utf8Str(it->first + "=" + it->second);
+
+ return Utf8Str("");
+}
+
+Utf8Str GuestEnvironment::Get(const Utf8Str &strKey)
+{
+ std::map <Utf8Str, Utf8Str>::const_iterator itEnv = mEnvironment.find(strKey);
+ Utf8Str strRet;
+ if (itEnv != mEnvironment.end())
+ strRet = itEnv->second;
+ return strRet;
+}
+
+bool GuestEnvironment::Has(const Utf8Str &strKey)
+{
+ std::map <Utf8Str, Utf8Str>::const_iterator itEnv = mEnvironment.find(strKey);
+ return (itEnv != mEnvironment.end());
+}
+
+int GuestEnvironment::Set(const Utf8Str &strKey, const Utf8Str &strValue)
+{
+ /** @todo Do some validation using regex. */
+ if (strKey.isEmpty())
+ return VERR_INVALID_PARAMETER;
+
+ int rc = VINF_SUCCESS;
+ const char *pszString = strKey.c_str();
+ while (*pszString != '\0' && RT_SUCCESS(rc))
+ {
+ if ( !RT_C_IS_ALNUM(*pszString)
+ && !RT_C_IS_GRAPH(*pszString))
+ rc = VERR_INVALID_PARAMETER;
+ *pszString++;
+ }
+
+ if (RT_SUCCESS(rc))
+ mEnvironment[strKey] = strValue;
+
+ return rc;
+}
+
+int GuestEnvironment::Set(const Utf8Str &strPair)
+{
+ RTCList<RTCString> listPair = strPair.split("=", RTCString::KeepEmptyParts);
+ /* Skip completely empty pairs. Note that we still need pairs with a valid
+ * (set) key and an empty value. */
+ if (listPair.size() <= 1)
+ return VINF_SUCCESS;
+
+ int rc = VINF_SUCCESS;
+ size_t p = 0;
+ while(p < listPair.size() && RT_SUCCESS(rc))
+ {
+ Utf8Str strKey = listPair.at(p++);
+ if ( strKey.isEmpty()
+ || strKey.equals("=")) /* Skip pairs with empty keys (e.g. "=FOO"). */
+ {
+ break;
+ }
+ Utf8Str strValue;
+ if (p < listPair.size()) /* Does the list also contain a value? */
+ strValue = listPair.at(p++);
+
+#ifdef DEBUG
+ LogFlowFunc(("strKey=%s, strValue=%s\n",
+ strKey.c_str(), strValue.c_str()));
+#endif
+ rc = Set(strKey, strValue);
+ }
+
+ return rc;
+}
+
+size_t GuestEnvironment::Size(void)
+{
+ return mEnvironment.size();
+}
+
+int GuestEnvironment::Unset(const Utf8Str &strKey)
+{
+ std::map <Utf8Str, Utf8Str>::iterator itEnv = mEnvironment.find(strKey);
+ if (itEnv != mEnvironment.end())
+ {
+ mEnvironment.erase(itEnv);
+ return VINF_SUCCESS;
+ }
+
+ return VERR_NOT_FOUND;
+}
+
+GuestEnvironment& GuestEnvironment::operator=(const GuestEnvironmentArray &that)
+{
+ CopyFrom(that);
+ return *this;
+}
+
+GuestEnvironment& GuestEnvironment::operator=(const GuestEnvironment &that)
+{
+ for (std::map<Utf8Str, Utf8Str>::const_iterator it = that.mEnvironment.begin();
+ it != that.mEnvironment.end();
+ ++it)
+ {
+ mEnvironment[it->first] = it->second;
+ }
+
+ return *this;
+}
+
+/**
+ * Appends environment variables to the environment block.
+ *
+ * Each var=value pair is separated by the null character ('\\0'). The whole
+ * block will be stored in one blob and disassembled on the guest side later to
+ * fit into the HGCM param structure.
+ *
+ * @returns VBox status code.
+ *
+ * @param pszEnvVar The environment variable=value to append to the
+ * environment block.
+ * @param ppvList This is actually a pointer to a char pointer
+ * variable which keeps track of the environment block
+ * that we're constructing.
+ * @param pcbList Pointer to the variable holding the current size of
+ * the environment block. (List is a misnomer, go
+ * ahead a be confused.)
+ * @param pcEnvVars Pointer to the variable holding count of variables
+ * stored in the environment block.
+ */
+int GuestEnvironment::appendToEnvBlock(const char *pszEnv, void **ppvList, size_t *pcbList, uint32_t *pcEnvVars)
+{
+ int rc = VINF_SUCCESS;
+ size_t cchEnv = strlen(pszEnv); Assert(cchEnv >= 2);
+ if (*ppvList)
+ {
+ size_t cbNewLen = *pcbList + cchEnv + 1; /* Include zero termination. */
+ char *pvTmp = (char *)RTMemRealloc(*ppvList, cbNewLen);
+ if (pvTmp == NULL)
+ rc = VERR_NO_MEMORY;
+ else
+ {
+ memcpy(pvTmp + *pcbList, pszEnv, cchEnv);
+ pvTmp[cbNewLen - 1] = '\0'; /* Add zero termination. */
+ *ppvList = (void **)pvTmp;
+ }
+ }
+ else
+ {
+ char *pszTmp;
+ if (RTStrAPrintf(&pszTmp, "%s", pszEnv) >= 0)
+ {
+ *ppvList = (void **)pszTmp;
+ /* Reset counters. */
+ *pcEnvVars = 0;
+ *pcbList = 0;
+ }
+ }
+ if (RT_SUCCESS(rc))
+ {
+ *pcbList += cchEnv + 1; /* Include zero termination. */
+ *pcEnvVars += 1; /* Increase env variable count. */
+ }
+ return rc;
+}
+
+int GuestFsObjData::FromLs(const GuestProcessStreamBlock &strmBlk)
+{
+ LogFlowFunc(("\n"));
+
+ int rc = VINF_SUCCESS;
+
+ try
+ {
+#ifdef DEBUG
+ strmBlk.DumpToLog();
+#endif
+ /* Object name. */
+ mName = strmBlk.GetString("name");
+ if (mName.isEmpty()) throw VERR_NOT_FOUND;
+ /* Type. */
+ Utf8Str strType(strmBlk.GetString("ftype"));
+ if (strType.equalsIgnoreCase("-"))
+ mType = FsObjType_File;
+ else if (strType.equalsIgnoreCase("d"))
+ mType = FsObjType_Directory;
+ /** @todo Add more types! */
+ else
+ mType = FsObjType_Undefined;
+ /* Object size. */
+ rc = strmBlk.GetInt64Ex("st_size", &mObjectSize);
+ if (RT_FAILURE(rc)) throw rc;
+ /** @todo Add complete ls info! */
+ }
+ catch (int rc2)
+ {
+ rc = rc2;
+ }
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+int GuestFsObjData::FromStat(const GuestProcessStreamBlock &strmBlk)
+{
+ LogFlowFunc(("\n"));
+
+ int rc = VINF_SUCCESS;
+
+ try
+ {
+#ifdef DEBUG
+ strmBlk.DumpToLog();
+#endif
+ /* Node ID, optional because we don't include this
+ * in older VBoxService (< 4.2) versions. */
+ mNodeID = strmBlk.GetInt64("node_id");
+ /* Object name. */
+ mName = strmBlk.GetString("name");
+ if (mName.isEmpty()) throw VERR_NOT_FOUND;
+ /* Type. */
+ Utf8Str strType(strmBlk.GetString("ftype"));
+ if (strType.equalsIgnoreCase("-"))
+ mType = FsObjType_File;
+ else if (strType.equalsIgnoreCase("d"))
+ mType = FsObjType_Directory;
+ /** @todo Add more types! */
+ else
+ mType = FsObjType_Undefined;
+ /* Object size. */
+ rc = strmBlk.GetInt64Ex("st_size", &mObjectSize);
+ if (RT_FAILURE(rc)) throw rc;
+ /** @todo Add complete stat info! */
+ }
+ catch (int rc2)
+ {
+ rc = rc2;
+ }
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** @todo *NOT* thread safe yet! */
+/** @todo Add exception handling for STL stuff! */
+
+GuestProcessStreamBlock::GuestProcessStreamBlock(void)
+{
+
+}
+
+/*
+GuestProcessStreamBlock::GuestProcessStreamBlock(const GuestProcessStreamBlock &otherBlock)
+{
+ for (GuestCtrlStreamPairsIter it = otherBlock.m_mapPairs.begin();
+ it != otherBlock.end(); it++)
+ {
+ m_mapPairs[it->first] = new
+ if (it->second.pszValue)
+ {
+ RTMemFree(it->second.pszValue);
+ it->second.pszValue = NULL;
+ }
+ }
+}*/
+
+GuestProcessStreamBlock::~GuestProcessStreamBlock()
+{
+ Clear();
+}
+
+/**
+ * Destroys the currently stored stream pairs.
+ *
+ * @return IPRT status code.
+ */
+void GuestProcessStreamBlock::Clear(void)
+{
+ m_mapPairs.clear();
+}
+
+#ifdef DEBUG
+void GuestProcessStreamBlock::DumpToLog(void) const
+{
+ LogFlowFunc(("Dumping contents of stream block=0x%p (%ld items):\n",
+ this, m_mapPairs.size()));
+
+ for (GuestCtrlStreamPairMapIterConst it = m_mapPairs.begin();
+ it != m_mapPairs.end(); it++)
+ {
+ LogFlowFunc(("\t%s=%s\n", it->first.c_str(), it->second.mValue.c_str()));
+ }
+}
+#endif
+
+/**
+ * Returns a 64-bit signed integer of a specified key.
+ *
+ * @return IPRT status code. VERR_NOT_FOUND if key was not found.
+ * @param pszKey Name of key to get the value for.
+ * @param piVal Pointer to value to return.
+ */
+int GuestProcessStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal) const
+{
+ AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
+ AssertPtrReturn(piVal, VERR_INVALID_POINTER);
+ const char *pszValue = GetString(pszKey);
+ if (pszValue)
+ {
+ *piVal = RTStrToInt64(pszValue);
+ return VINF_SUCCESS;
+ }
+ return VERR_NOT_FOUND;
+}
+
+/**
+ * Returns a 64-bit integer of a specified key.
+ *
+ * @return int64_t Value to return, 0 if not found / on failure.
+ * @param pszKey Name of key to get the value for.
+ */
+int64_t GuestProcessStreamBlock::GetInt64(const char *pszKey) const
+{
+ int64_t iVal;
+ if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
+ return iVal;
+ return 0;
+}
+
+/**
+ * Returns the current number of stream pairs.
+ *
+ * @return uint32_t Current number of stream pairs.
+ */
+size_t GuestProcessStreamBlock::GetCount(void) const
+{
+ return m_mapPairs.size();
+}
+
+/**
+ * Returns a string value of a specified key.
+ *
+ * @return uint32_t Pointer to string to return, NULL if not found / on failure.
+ * @param pszKey Name of key to get the value for.
+ */
+const char* GuestProcessStreamBlock::GetString(const char *pszKey) const
+{
+ AssertPtrReturn(pszKey, NULL);
+
+ try
+ {
+ GuestCtrlStreamPairMapIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));
+ if (itPairs != m_mapPairs.end())
+ return itPairs->second.mValue.c_str();
+ }
+ catch (const std::exception &ex)
+ {
+ NOREF(ex);
+ }
+ return NULL;
+}
+
+/**
+ * Returns a 32-bit unsigned integer of a specified key.
+ *
+ * @return IPRT status code. VERR_NOT_FOUND if key was not found.
+ * @param pszKey Name of key to get the value for.
+ * @param puVal Pointer to value to return.
+ */
+int GuestProcessStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) const
+{
+ AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
+ AssertPtrReturn(puVal, VERR_INVALID_POINTER);
+ const char *pszValue = GetString(pszKey);
+ if (pszValue)
+ {
+ *puVal = RTStrToUInt32(pszValue);
+ return VINF_SUCCESS;
+ }
+ return VERR_NOT_FOUND;
+}
+
+/**
+ * Returns a 32-bit unsigned integer of a specified key.
+ *
+ * @return uint32_t Value to return, 0 if not found / on failure.
+ * @param pszKey Name of key to get the value for.
+ */
+uint32_t GuestProcessStreamBlock::GetUInt32(const char *pszKey) const
+{
+ uint32_t uVal;
+ if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
+ return uVal;
+ return 0;
+}
+
+/**
+ * Sets a value to a key or deletes a key by setting a NULL value.
+ *
+ * @return IPRT status code.
+ * @param pszKey Key name to process.
+ * @param pszValue Value to set. Set NULL for deleting the key.
+ */
+int GuestProcessStreamBlock::SetValue(const char *pszKey, const char *pszValue)
+{
+ AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
+
+ int rc = VINF_SUCCESS;
+ try
+ {
+ Utf8Str Utf8Key(pszKey);
+
+ /* Take a shortcut and prevent crashes on some funny versions
+ * of STL if map is empty initially. */
+ if (!m_mapPairs.empty())
+ {
+ GuestCtrlStreamPairMapIter it = m_mapPairs.find(Utf8Key);
+ if (it != m_mapPairs.end())
+ m_mapPairs.erase(it);
+ }
+
+ if (pszValue)
+ {
+ GuestProcessStreamValue val(pszValue);
+ m_mapPairs[Utf8Key] = val;
+ }
+ }
+ catch (const std::exception &ex)
+ {
+ NOREF(ex);
+ }
+ return rc;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GuestProcessStream::GuestProcessStream(void)
+ : m_cbAllocated(0),
+ m_cbSize(0),
+ m_cbOffset(0),
+ m_pbBuffer(NULL)
+{
+
+}
+
+GuestProcessStream::~GuestProcessStream(void)
+{
+ Destroy();
+}
+
+/**
+ * Adds data to the internal parser buffer. Useful if there
+ * are multiple rounds of adding data needed.
+ *
+ * @return IPRT status code.
+ * @param pbData Pointer to data to add.
+ * @param cbData Size (in bytes) of data to add.
+ */
+int GuestProcessStream::AddData(const BYTE *pbData, size_t cbData)
+{
+ AssertPtrReturn(pbData, VERR_INVALID_POINTER);
+ AssertReturn(cbData, VERR_INVALID_PARAMETER);
+
+ int rc = VINF_SUCCESS;
+
+ /* Rewind the buffer if it's empty. */
+ size_t cbInBuf = m_cbSize - m_cbOffset;
+ bool const fAddToSet = cbInBuf == 0;
+ if (fAddToSet)
+ m_cbSize = m_cbOffset = 0;
+
+ /* Try and see if we can simply append the data. */
+ if (cbData + m_cbSize <= m_cbAllocated)
+ {
+ memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
+ m_cbSize += cbData;
+ }
+ else
+ {
+ /* Move any buffered data to the front. */
+ cbInBuf = m_cbSize - m_cbOffset;
+ if (cbInBuf == 0)
+ m_cbSize = m_cbOffset = 0;
+ else if (m_cbOffset) /* Do we have something to move? */
+ {
+ memmove(m_pbBuffer, &m_pbBuffer[m_cbOffset], cbInBuf);
+ m_cbSize = cbInBuf;
+ m_cbOffset = 0;
+ }
+
+ /* Do we need to grow the buffer? */
+ if (cbData + m_cbSize > m_cbAllocated)
+ {
+ size_t cbAlloc = m_cbSize + cbData;
+ cbAlloc = RT_ALIGN_Z(cbAlloc, _64K);
+ void *pvNew = RTMemRealloc(m_pbBuffer, cbAlloc);
+ if (pvNew)
+ {
+ m_pbBuffer = (uint8_t *)pvNew;
+ m_cbAllocated = cbAlloc;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+
+ /* Finally, copy the data. */
+ if (RT_SUCCESS(rc))
+ {
+ if (cbData + m_cbSize <= m_cbAllocated)
+ {
+ memcpy(&m_pbBuffer[m_cbSize], pbData, cbData);
+ m_cbSize += cbData;
+ }
+ else
+ rc = VERR_BUFFER_OVERFLOW;
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Destroys the internal data buffer.
+ */
+void GuestProcessStream::Destroy(void)
+{
+ if (m_pbBuffer)
+ {
+ RTMemFree(m_pbBuffer);
+ m_pbBuffer = NULL;
+ }
+
+ m_cbAllocated = 0;
+ m_cbSize = 0;
+ m_cbOffset = 0;
+}
+
+#ifdef DEBUG
+void GuestProcessStream::Dump(const char *pszFile)
+{
+ LogFlowFunc(("Dumping contents of stream=0x%p (cbAlloc=%u, cbSize=%u, cbOff=%u) to %s\n",
+ m_pbBuffer, m_cbAllocated, m_cbSize, m_cbOffset, pszFile));
+
+ RTFILE hFile;
+ int rc = RTFileOpen(&hFile, pszFile, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTFileWrite(hFile, m_pbBuffer, m_cbSize, NULL /* pcbWritten */);
+ RTFileClose(hFile);
+ }
+}
+#endif
+
+/**
+ * Returns the current offset of the parser within
+ * the internal data buffer.
+ *
+ * @return uint32_t Parser offset.
+ */
+uint32_t GuestProcessStream::GetOffset()
+{
+ return m_cbOffset;
+}
+
+uint32_t GuestProcessStream::GetSize()
+{
+ return m_cbSize;
+}
+
+/**
+ * Tries to parse the next upcoming pair block within the internal
+ * buffer.
+ *
+ * Returns VERR_NO_DATA is no data is in internal buffer or buffer has been
+ * completely parsed already.
+ *
+ * Returns VERR_MORE_DATA if current block was parsed (with zero or more pairs
+ * stored in stream block) but still contains incomplete (unterminated)
+ * data.
+ *
+ * Returns VINF_SUCCESS if current block was parsed until the next upcoming
+ * block (with zero or more pairs stored in stream block).
+ *
+ * @return IPRT status code.
+ * @param streamBlock Reference to guest stream block to fill.
+ *
+ */
+int GuestProcessStream::ParseBlock(GuestProcessStreamBlock &streamBlock)
+{
+ if ( !m_pbBuffer
+ || !m_cbSize)
+ {
+ return VERR_NO_DATA;
+ }
+
+ AssertReturn(m_cbOffset <= m_cbSize, VERR_INVALID_PARAMETER);
+ if (m_cbOffset == m_cbSize)
+ return VERR_NO_DATA;
+
+ int rc = VINF_SUCCESS;
+
+ char *pszOff = (char*)&m_pbBuffer[m_cbOffset];
+ char *pszStart = pszOff;
+ uint32_t uDistance;
+ while (*pszStart)
+ {
+ size_t pairLen = strlen(pszStart);
+ uDistance = (pszStart - pszOff);
+ if (m_cbOffset + uDistance + pairLen + 1 >= m_cbSize)
+ {
+ rc = VERR_MORE_DATA;
+ break;
+ }
+ else
+ {
+ char *pszSep = strchr(pszStart, '=');
+ char *pszVal = NULL;
+ if (pszSep)
+ pszVal = pszSep + 1;
+ if (!pszSep || !pszVal)
+ {
+ rc = VERR_MORE_DATA;
+ break;
+ }
+
+ /* Terminate the separator so that we can
+ * use pszStart as our key from now on. */
+ *pszSep = '\0';
+
+ rc = streamBlock.SetValue(pszStart, pszVal);
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ /* Next pair. */
+ pszStart += pairLen + 1;
+ }
+
+ /* If we did not do any movement but we have stuff left
+ * in our buffer just skip the current termination so that
+ * we can try next time. */
+ uDistance = (pszStart - pszOff);
+ if ( !uDistance
+ && *pszStart == '\0'
+ && m_cbOffset < m_cbSize)
+ {
+ uDistance++;
+ }
+ m_cbOffset += uDistance;
+
+ return rc;
+}
+
diff --git a/src/VBox/Main/src-client/GuestDirEntryImpl.cpp b/src/VBox/Main/src-client/GuestDirEntryImpl.cpp
deleted file mode 100644
index 6f7de2200..000000000
--- a/src/VBox/Main/src-client/GuestDirEntryImpl.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/* $Id: GuestDirEntryImpl.cpp $ */
-/** @file
- * VirtualBox Main - interface for guest directory entries, VBoxC.
- */
-
-/*
- * Copyright (C) 2011 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-
-/*******************************************************************************
-* Header Files *
-*******************************************************************************/
-#include "GuestDirEntryImpl.h"
-#include "GuestCtrlImplPrivate.h"
-#include "Global.h"
-
-#include "AutoCaller.h"
-#include "Logging.h"
-
-
-// constructor / destructor
-/////////////////////////////////////////////////////////////////////////////
-
-DEFINE_EMPTY_CTOR_DTOR(GuestDirEntry)
-
-HRESULT GuestDirEntry::FinalConstruct()
-{
- LogFlowThisFunc(("\n"));
- return BaseFinalConstruct();
-}
-
-void GuestDirEntry::FinalRelease()
-{
- LogFlowThisFuncEnter();
- uninit();
- BaseFinalRelease();
- LogFlowThisFuncLeave();
-}
-
-// public initializer/uninitializer for internal purposes only
-/////////////////////////////////////////////////////////////////////////////
-
-HRESULT GuestDirEntry::init(Guest *aParent, GuestProcessStreamBlock &streamBlock)
-{
- LogFlowThisFunc(("aParent=%p\n", aParent));
-
- /* Enclose the state transition NotReady->InInit->Ready. */
- AutoInitSpan autoInitSpan(this);
- AssertReturn(autoInitSpan.isOk(), E_FAIL);
-
- mData.mNodeId = streamBlock.GetInt64("node_id");
- const char *pszName = streamBlock.GetString("name");
- if (pszName)
- {
- mData.mName = BstrFmt("%s", pszName);
- mData.mType = GuestDirEntry::fileTypeToEntryType(streamBlock.GetString("ftype"));
-
- /* Confirm a successful initialization when it's the case. */
- autoInitSpan.setSucceeded();
-
- return S_OK;
- }
-
- return E_FAIL; /** @todo Find a better rc! */
-}
-
-/**
- * Uninitializes the instance.
- * Called from FinalRelease().
- */
-void GuestDirEntry::uninit()
-{
- LogFlowThisFunc(("\n"));
-
- /* Enclose the state transition Ready->InUninit->NotReady. */
- AutoUninitSpan autoUninitSpan(this);
- if (autoUninitSpan.uninitDone())
- return;
-}
-
-STDMETHODIMP GuestDirEntry::COMGETTER(NodeId)(LONG64 *aNodeId)
-{
- LogFlowThisFuncEnter();
-
- CheckComArgOutPointerValid(aNodeId);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- *aNodeId = mData.mNodeId;
-
- return S_OK;
-}
-
-STDMETHODIMP GuestDirEntry::COMGETTER(Name)(BSTR *aName)
-{
- LogFlowThisFuncEnter();
-
- CheckComArgOutPointerValid(aName);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- mData.mName.cloneTo(aName);
-
- return S_OK;
-}
-
-STDMETHODIMP GuestDirEntry::COMGETTER(Type)(GuestDirEntryType_T *aType)
-{
- LogFlowThisFuncEnter();
-
- CheckComArgOutPointerValid(aType);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- *aType = mData.mType;
-
- return S_OK;
-}
-
-GuestDirEntryType_T GuestDirEntry::fileTypeToEntryType(const char *pszFileType)
-{
- GuestDirEntryType_T retType = GuestDirEntryType_Unknown;
-
- if (!pszFileType)
- return retType;
-
- if (!RTStrICmp(pszFileType, "-"))
- retType = GuestDirEntryType_File;
- else if (!RTStrICmp(pszFileType, "d"))
- retType = GuestDirEntryType_Directory;
- else if (!RTStrICmp(pszFileType, "l"))
- retType = GuestDirEntryType_Symlink;
- /** @todo Add more types here. */
-
- return retType;
-}
-
diff --git a/src/VBox/Main/src-client/GuestDirectoryImpl.cpp b/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
new file mode 100644
index 000000000..36d262b95
--- /dev/null
+++ b/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
@@ -0,0 +1,296 @@
+
+/* $Id: GuestDirectoryImpl.cpp $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "GuestDirectoryImpl.h"
+#include "GuestSessionImpl.h"
+#include "GuestCtrlImplPrivate.h"
+
+#include "Global.h"
+#include "AutoCaller.h"
+
+#include <VBox/com/array.h>
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
+#include <VBox/log.h>
+
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR(GuestDirectory)
+
+HRESULT GuestDirectory::FinalConstruct(void)
+{
+ LogFlowThisFunc(("\n"));
+ return BaseFinalConstruct();
+}
+
+void GuestDirectory::FinalRelease(void)
+{
+ LogFlowThisFuncEnter();
+ uninit();
+ BaseFinalRelease();
+ LogFlowThisFuncLeave();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+int GuestDirectory::init(GuestSession *aSession,
+ const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags)
+{
+ LogFlowThisFunc(("strPath=%s, strFilter=%s, uFlags=%x\n",
+ strPath.c_str(), strFilter.c_str(), uFlags));
+
+ /* Enclose the state transition NotReady->InInit->Ready. */
+ AutoInitSpan autoInitSpan(this);
+ AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+ mData.mSession = aSession;
+ mData.mName = strPath;
+ mData.mFilter = strFilter;
+ mData.mFlags = uFlags;
+
+ /* Start the directory process on the guest. */
+ GuestProcessStartupInfo procInfo;
+ procInfo.mName = Utf8StrFmt(tr("Reading directory \"%s\"", strPath.c_str()));
+ procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_LS);
+ procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
+ procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
+
+ procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
+ /* We want the long output format which contains all the object details. */
+ procInfo.mArguments.push_back(Utf8Str("-l"));
+#if 0 /* Flags are not supported yet. */
+ if (uFlags & DirectoryOpenFlag_NoSymlinks)
+ procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
+#endif
+ /** @todo Recursion support? */
+ procInfo.mArguments.push_back(strPath); /* The directory we want to open. */
+
+ /*
+ * Start the process asynchronously and keep it around so that we can use
+ * it later in subsequent read() calls.
+ * Note: No guest rc available because operation is asynchronous.
+ */
+ int rc = mData.mProcessTool.Init(mData.mSession, procInfo,
+ true /* Async */, NULL /* Guest rc */);
+ if (RT_SUCCESS(rc))
+ {
+ /* Confirm a successful initialization when it's the case. */
+ autoInitSpan.setSucceeded();
+ return rc;
+ }
+
+ autoInitSpan.setFailed();
+ return rc;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called from FinalRelease().
+ */
+void GuestDirectory::uninit(void)
+{
+ LogFlowThisFunc(("\n"));
+
+ /* Enclose the state transition Ready->InUninit->NotReady. */
+ AutoUninitSpan autoUninitSpan(this);
+ if (autoUninitSpan.uninitDone())
+ return;
+
+ LogFlowThisFuncLeave();
+}
+
+// implementation of public getters/setters for attributes
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestDirectory::COMGETTER(DirectoryName)(BSTR *aName)
+{
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aName);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mName.cloneTo(aName);
+
+ return S_OK;
+}
+
+STDMETHODIMP GuestDirectory::COMGETTER(Filter)(BSTR *aFilter)
+{
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aFilter);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mFilter.cloneTo(aFilter);
+
+ return S_OK;
+}
+
+// private methods
+/////////////////////////////////////////////////////////////////////////////
+
+// implementation of public methods
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestDirectory::Close(void)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AssertPtr(mData.mSession);
+ int rc = mData.mSession->directoryRemoveFromList(this);
+
+ mData.mProcessTool.Terminate();
+
+ /*
+ * Release autocaller before calling uninit.
+ */
+ autoCaller.release();
+
+ uninit();
+
+ LogFlowFuncLeaveRC(rc);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestDirectory::Read(IFsObjInfo **aInfo)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ GuestProcessStreamBlock curBlock;
+ int guestRc;
+
+ int rc = mData.mProcessTool.WaitEx(GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK,
+ &curBlock, &guestRc);
+
+ /*
+ * Note: The guest process can still be around to serve the next
+ * upcoming stream block next time.
+ */
+ if ( RT_SUCCESS(rc)
+ && !mData.mProcessTool.IsRunning())
+ {
+ rc = mData.mProcessTool.TerminatedOk(NULL /* Exit code */);
+ if (rc == VERR_NOT_EQUAL)
+ rc = VERR_ACCESS_DENIED;
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ if (curBlock.GetCount()) /* Did we get content? */
+ {
+ GuestFsObjData objData;
+ rc = objData.FromLs(curBlock);
+ if (RT_FAILURE(rc))
+ rc = VERR_PATH_NOT_FOUND;
+
+ if (RT_SUCCESS(rc))
+ {
+ /* Create the object. */
+ ComObjPtr<GuestFsObjInfo> pFsObjInfo;
+ HRESULT hr2 = pFsObjInfo.createObject();
+ if (FAILED(hr2))
+ rc = VERR_COM_UNEXPECTED;
+
+ if (RT_SUCCESS(rc))
+ rc = pFsObjInfo->init(objData);
+
+ if (RT_SUCCESS(rc))
+ {
+ /* Return info object to the caller. */
+ hr2 = pFsObjInfo.queryInterfaceTo(aInfo);
+ if (FAILED(hr2))
+ rc = VERR_COM_UNEXPECTED;
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to read anymore. Tell the caller. */
+ rc = VERR_NO_MORE_FILES;
+ }
+ }
+
+ HRESULT hr = S_OK;
+
+ if (RT_FAILURE(rc)) /** @todo Add more errors here. */
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ case VERR_ACCESS_DENIED:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"),
+ mData.mName.c_str());
+ break;
+
+ case VERR_PATH_NOT_FOUND:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Path not found"),
+ mData.mName.c_str());
+ break;
+
+ case VERR_NO_MORE_FILES:
+ /* See SDK reference. */
+ hr = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No more entries for directory \"%s\""),
+ mData.mName.c_str());
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"),
+ mData.mName.c_str(), rc);
+ break;
+ }
+ }
+
+ LogFlowFuncLeaveRC(rc);
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
diff --git a/src/VBox/Main/src-client/GuestDnDImpl.cpp b/src/VBox/Main/src-client/GuestDnDImpl.cpp
new file mode 100644
index 000000000..2e07a950d
--- /dev/null
+++ b/src/VBox/Main/src-client/GuestDnDImpl.cpp
@@ -0,0 +1,995 @@
+/* $Id: GuestDnDImpl.cpp $ */
+/** @file
+ * VirtualBox COM class implementation: Guest Drag and Drop parts
+ */
+
+/*
+ * Copyright (C) 2011-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "GuestImpl.h"
+#include "AutoCaller.h"
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+# include "ConsoleImpl.h"
+# include "ProgressImpl.h"
+# include "GuestDnDImpl.h"
+
+# include <VMMDev.h>
+
+# include <VBox/com/list.h>
+# include <VBox/HostServices/DragAndDropSvc.h>
+
+# include <iprt/stream.h>
+# include <iprt/semaphore.h>
+# include <iprt/cpp/utils.h>
+
+/* How does this work:
+ *
+ * Drag and Drop is handled over the internal HGCM service for the host <->
+ * guest communication. Beside that we need to map the Drag and Drop protocols
+ * of the various OS's we support to our internal channels, this is also highly
+ * communicative in both directions. Unfortunately HGCM isn't really designed
+ * for that. Next we have to foul some of the components. This includes to
+ * trick X11 on the guest side, but also Qt needs to be tricked on the host
+ * side a little bit.
+ *
+ * The following components are involved:
+ *
+ * 1. GUI: Uses the Qt classes for Drag and Drop and mainly forward the content
+ * of it to the Main IGuest interface (see UIDnDHandler.cpp).
+ * 2. Main: Public interface for doing Drag and Drop. Also manage the IProgress
+ * interfaces for blocking the caller by showing a progress dialog. (see
+ * this file)
+ * 3. HGCM service: Handle all messages from the host to the guest at once and
+ * encapsulate the internal communication details. (see dndmanager.cpp and
+ * friends)
+ * 4. Guest additions: Split into the platform neutral part (see
+ * VBoxGuestR3LibDragAndDrop.cpp) and the guest OS specific parts.
+ * Receive/send message from/to the HGCM service and does all guest specific
+ * operations. Currently only X11 is supported. (see draganddrop.cpp within
+ * VBoxClient)
+ *
+ * Host -> Guest:
+ * 1. There are DnD Enter, Move, Leave events which are send exactly like this
+ * to the guest. The info includes the pos, mimetypes and allowed actions.
+ * The guest has to respond with an action it would accept, so the GUI could
+ * change the cursor.
+ * 2. On drop, first a drop event is send. If this is accepted a drop data
+ * event follows. This blocks the GUI and shows some progress indicator.
+ *
+ * Guest -> Host:
+ * 1. The GUI is asking the guest if a DnD event is pending when the user moves
+ * the cursor out of the view window. If so, this returns the mimetypes and
+ * allowed actions.
+ * (2. On every mouse move this is asked again, to make sure the DnD event is
+ * still valid.)
+ * 3. On drop the host request the data from the guest. This blocks the GUI and
+ * shows some progress indicator.
+ *
+ * Some hints:
+ * m_sstrAllowedMimeTypes here in this file defines the allowed mime-types.
+ * This is necessary because we need special handling for some of the
+ * mime-types. E.g. for URI lists we need to transfer the actual dirs and
+ * files. Text EOL may to be changed. Also unknown mime-types may need special
+ * handling as well, which may lead to undefined behavior in the host/guest, if
+ * not done.
+ *
+ * Dropping of a directory, means recursively transferring _all_ the content.
+ *
+ * Directories and files are placed into a public visible user directory on the
+ * guest (~/Documents/VirtualBox Dropped Files). We can't delete them after the
+ * DnD operation, because we didn't know what the DnD target does with it. E.g.
+ * it could just be opened in place. This could lead ofc to filling up the disk
+ * within the guest. To inform the user about this, a small app could be
+ * developed which scans this directory regularly and inform the user with a
+ * tray icon hint (and maybe the possibility to clean this up instantly). The
+ * same has to be done in the G->H direction when it is implemented.
+ *
+ * Of course only regularly files are supported. Symlinks are resolved and
+ * transfered as regularly files. First we don't know if the other side support
+ * symlinks at all and second they could point to somewhere in a directory tree
+ * which not exists on the other side.
+ *
+ * The code tries to preserve the file modes of the transfered dirs/files. This
+ * is useful (and maybe necessary) for two things:
+ * 1. If a file is executable, it should be also after the transfer, so the
+ * user can just execute it, without manually tweaking the modes first.
+ * 2. If a dir/file is not accessible by group/others in the host, it shouldn't
+ * be in the guest.
+ * In any case, the user mode is always set to rwx (so that we can access it
+ * ourself, in e.g. for a cleanup case after cancel).
+ *
+ * Cancel is supported in both directions and cleans up all previous steps
+ * (thats is: deleting already transfered dirs/files).
+ *
+ * There are a lot of DO (debug output) calls in the code. This could be
+ * disabled, but should be removed (or replaced by Log calls) when this is
+ * nearly finished.
+ *
+ * For Windows guests there could be different communication become necessary.
+ * So the current interface isn't set in stone and should be made public only,
+ * after someone had deeply looked into the Win guest support. See
+ * http://www.catch22.net/tuts/dragdrop for a start.
+ *
+ * How to test:
+ * First set VBOX_WITH_DRAG_AND_DROP=1 in LocalConfig.kmk. The best is if the
+ * host match the guest OS arch. Just build the tree and point a shared folder
+ * within the guest to the additions subfolder in bin. Start the guest and
+ * execute ./VBoxClient --dragandrop --nodaemon within this shared folder. You
+ * should now be able of dragging text or files to the guest. I used a 64bit
+ * Linux for both the host and the guest. If the archs don't match, you need to
+ * first setup a build environment in the guest ofc.
+ *
+ * In general I propose the following changes in the VBox HGCM infrastructure
+ * for the future:
+ * - Currently it isn't really possible to send messages to the guest from the
+ * host. The host informs the guest just that there is something, the guest
+ * than has to ask which message and depending on that send the appropriate
+ * message to the host, which is filled with the right data.
+ * - There is no generic interface for sending bigger memory blocks to/from the
+ * guest. This is now done here, but I guess was also necessary for e.g.
+ * guest execution. So something generic which brake this up into smaller
+ * blocks and send it would be nice (with all the error handling and such
+ * ofc).
+ * - I developed a "protocol" for the DnD communication here. So the host and
+ * the guest have always to match in the revision. This is ofc bad, because
+ * the additions could be outdated easily. So some generic protocol number
+ * support in HGCM for asking the host and the guest of the support version,
+ * would be nice. Ofc at least the host should be able to talk to the guest,
+ * even when the version is below the host one.
+ * All this stuff would be useful for the current services, but also for future
+ * onces.
+ *
+ * Todo:
+ * - Dragging out of the guest (partly done)
+ * - ESC doesn't really work
+ * - transfer of URIs (that is the files and patching of the data)
+ * - testing in a multi monitor setup
+ * ... in any case it seems a little bit difficult to handle from the Qt
+ * side. Maybe also a host specific implementation becomes necessary ...
+ * this would be really worst ofc.
+ * - Win guest support (maybe there have to be done a mapping between the
+ * official mime-types and Win Clipboard formats (see QWindowsMime, for an
+ * idea), for VBox internally only mime-types should be used)
+ * - EOL handling on text (should be shared with the clipboard code)
+ * - add configuration (GH, HG, Bidirectional, None), like for the clipboard
+ * - HG->GH and GH->HG-switch: Handle the case the user drags something out of
+ * the guest and than return to the source view (or another window in the
+ * multiple guest screen scenario).
+ * - add support for more mime-types (especially images, csv)
+ * - test unusual behavior:
+ * - DnD service crash in the guest during a DnD op (e.g. crash of VBoxClient or X11)
+ * - not expected order of the events between HGCM and the guest
+ * - Security considerations: We transfer a lot of memory between the guest and
+ * the host and even allow the creation of dirs/files. Maybe there should be
+ * limits introduced to preventing DOS attacks or filling up all the memory
+ * (both in the host and the guest).
+ * - test, test, test ...
+ */
+
+class DnDGuestResponse
+{
+public:
+ DnDGuestResponse(const ComObjPtr<Guest>& pGuest);
+ ~DnDGuestResponse();
+
+ int notifyAboutGuestResponse();
+ int waitForGuestResponse();
+
+ void setDefAction(uint32_t a) { m_defAction = a; }
+ uint32_t defAction() const { return m_defAction; }
+
+ void setAllActions(uint32_t a) { m_allActions = a; }
+ uint32_t allActions() const { return m_allActions; }
+
+ void setFormat(const Utf8Str &strFormat) { m_strFormat = strFormat; }
+ Utf8Str format() const { return m_strFormat; }
+
+ int addData(void *pvData, uint32_t cbData, uint32_t *pcbCurSize);
+ void resetData();
+ void data(void **ppvData, uint32_t *pcbData) const { *ppvData = m_pvData; *pcbData = m_cbData; }
+ bool hasData() const { return m_pvData != NULL; }
+
+ int setProgress(unsigned uPercentage, uint32_t uState, int rcOp = VINF_SUCCESS);
+ HRESULT resetProgress(const ComObjPtr<Guest>& pParent);
+ HRESULT queryProgressTo(IProgress **ppProgress);
+
+private:
+ RTSEMEVENT m_EventSem;
+ uint32_t m_defAction;
+ uint32_t m_allActions;
+ Utf8Str m_strFormat;
+ void *m_pvData;
+ uint32_t m_cbData;
+
+ ComObjPtr<Guest> m_parent;
+ ComObjPtr<Progress> m_progress;
+};
+
+class GuestDnDPrivate
+{
+private:
+ /* todo: currently we only support one response. Maybe this needs to be extended at some time. */
+ GuestDnDPrivate(GuestDnD *q, const ComObjPtr<Guest>& pGuest)
+ : q_ptr(q)
+ , p(pGuest)
+ , m_pDnDResponse(new DnDGuestResponse(pGuest))
+ {}
+ ~GuestDnDPrivate() { delete m_pDnDResponse; }
+
+ DnDGuestResponse *response() const { return m_pDnDResponse; }
+
+ void adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const;
+ void hostCall(const char* psczFunction, uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;
+
+ /* Static helper */
+ static RTCString toFormatString(ComSafeArrayIn(IN_BSTR, formats));
+ static void toFormatSafeArray(const RTCString &strFormats, ComSafeArrayOut(BSTR, formats));
+
+ static DragAndDropAction_T toMainAction(uint32_t uAction);
+ static void toMainActions(uint32_t uActions, ComSafeArrayOut(DragAndDropAction_T, actions));
+ static uint32_t toHGCMAction(DragAndDropAction_T action);
+ static void toHGCMActions(DragAndDropAction_T inDefAction, uint32_t *pOutDefAction, ComSafeArrayIn(DragAndDropAction_T, inAllowedActions), uint32_t *pOutAllowedActions);
+
+ /* Private q and parent pointer */
+ GuestDnD *q_ptr;
+ ComObjPtr<Guest> p;
+
+ /* Private helper members */
+ static const RTCList<RTCString> m_sstrAllowedMimeTypes;
+ DnDGuestResponse *m_pDnDResponse;
+
+ friend class GuestDnD;
+};
+
+/* What mime-types are supported by VirtualBox.
+ * Note: If you add something here, make sure you test it with all guest OS's!
+ */
+/* static */
+const RTCList<RTCString> GuestDnDPrivate::m_sstrAllowedMimeTypes = RTCList<RTCString>()
+ /* Uri's */
+ << "text/uri-list"
+ /* Text */
+ << "text/plain;charset=utf-8"
+ << "UTF8_STRING"
+ << "text/plain"
+ << "COMPOUND_TEXT"
+ << "TEXT"
+ << "STRING"
+ /* OpenOffice formates */
+ << "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""
+ << "application/x-openoffice-drawing;windows_formatname=\"Drawing Format\"";
+
+DnDGuestResponse::DnDGuestResponse(const ComObjPtr<Guest>& pGuest)
+ : m_EventSem(NIL_RTSEMEVENT)
+ , m_defAction(0)
+ , m_allActions(0)
+ , m_pvData(0)
+ , m_cbData(0)
+ , m_parent(pGuest)
+{
+ int rc = RTSemEventCreate(&m_EventSem);
+ AssertRC(rc);
+}
+
+DnDGuestResponse::~DnDGuestResponse()
+{
+ resetData();
+ int rc = RTSemEventDestroy(m_EventSem);
+ AssertRC(rc);
+}
+
+int DnDGuestResponse::notifyAboutGuestResponse()
+{
+ return RTSemEventSignal(m_EventSem);
+}
+
+int DnDGuestResponse::waitForGuestResponse()
+{
+ return RTSemEventWait(m_EventSem, 300);
+}
+
+int DnDGuestResponse::addData(void *pvData, uint32_t cbData, uint32_t *pcbCurSize)
+{
+ int rc = VINF_SUCCESS;
+ m_pvData = RTMemRealloc(m_pvData, m_cbData + cbData);
+ if (m_pvData)
+ {
+ memcpy(&static_cast<uint8_t*>(m_pvData)[m_cbData], pvData, cbData);
+ m_cbData += cbData;
+ *pcbCurSize = m_cbData;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ return rc;
+}
+
+void DnDGuestResponse::resetData()
+{
+ if (m_pvData)
+ {
+ RTMemFree(m_pvData);
+ m_pvData = NULL;
+ }
+ m_cbData = 0;
+}
+
+HRESULT DnDGuestResponse::resetProgress(const ComObjPtr<Guest>& pParent)
+{
+ m_progress.setNull();
+ HRESULT rc = m_progress.createObject();
+ if (SUCCEEDED(rc))
+ {
+ rc = m_progress->init(static_cast<IGuest*>(pParent),
+ Bstr(pParent->tr("Dropping data")).raw(),
+ TRUE);
+ }
+ return rc;
+}
+
+int DnDGuestResponse::setProgress(unsigned uPercentage, uint32_t uState, int rcOp /* = VINF_SUCCESS */)
+{
+ int vrc = VINF_SUCCESS;
+ HRESULT rc;
+ if (!m_progress.isNull())
+ {
+ BOOL fCompleted;
+ rc = m_progress->COMGETTER(Completed)(&fCompleted);
+ if (!fCompleted)
+ {
+ if (uState == DragAndDropSvc::DND_PROGRESS_ERROR)
+ rc = m_progress->notifyComplete(E_FAIL,
+ COM_IIDOF(IGuest),
+ m_parent->getComponentName(),
+ m_parent->tr("Guest error (%Rrc)"), rcOp);
+ else if (uState == DragAndDropSvc::DND_PROGRESS_CANCELLED)
+ rc = m_progress->notifyComplete(S_OK);
+ else
+ {
+ rc = m_progress->SetCurrentOperationProgress(uPercentage);
+ if ( uState == DragAndDropSvc::DND_PROGRESS_COMPLETE
+ || uPercentage >= 100)
+ rc = m_progress->notifyComplete(S_OK);
+ }
+ }
+ BOOL fCanceled = FALSE;
+ rc = m_progress->COMGETTER(Canceled)(&fCanceled);
+ if (fCanceled)
+ vrc = VERR_CANCELLED;
+ }
+ return vrc;
+}
+
+HRESULT DnDGuestResponse::queryProgressTo(IProgress **ppProgress)
+{
+ return m_progress.queryInterfaceTo(ppProgress);
+}
+
+void GuestDnDPrivate::adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const
+{
+ /* For multi-monitor support we need to add shift values to the coordinates
+ * (depending on the screen number). */
+ ComPtr<IDisplay> pDisplay;
+ HRESULT rc = p->mParent->COMGETTER(Display)(pDisplay.asOutParam());
+ if (FAILED(rc)) throw rc;
+ ComPtr<IFramebuffer> pFramebuffer;
+ LONG xShift, yShift;
+ rc = pDisplay->GetFramebuffer(uScreenId, pFramebuffer.asOutParam(), &xShift, &yShift);
+ if (FAILED(rc)) throw rc;
+ *puX += xShift;
+ *puY += yShift;
+}
+
+void GuestDnDPrivate::hostCall(const char* psczFunction, uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const
+{
+ VMMDev *vmmDev = 0;
+ {
+ /* Make sure mParent is valid, so set the read lock while using.
+ * Do not keep this lock while doing the actual call, because in the meanwhile
+ * another thread could request a write lock which would be a bad idea ... */
+ AutoReadLock alock(p COMMA_LOCKVAL_SRC_POS);
+
+ /* Forward the information to the VMM device. */
+ AssertPtr(p->mParent);
+ vmmDev = p->mParent->getVMMDev();
+ }
+
+ if (!vmmDev)
+ throw p->setError(VBOX_E_VM_ERROR,
+ p->tr("VMM device is not available (is the VM running?)"));
+
+ LogFlowFunc(("hgcmHostCall msg=%s; numParms=%u\n", psczFunction, u32Function));
+ int vrc = vmmDev->hgcmHostCall("VBoxDragAndDropSvc",
+ u32Function,
+ cParms, paParms);
+ if (RT_FAILURE(vrc))
+ {
+ LogFlowFunc(("hgcmHostCall error: %Rrc\n", vrc));
+ throw p->setError(VBOX_E_VM_ERROR,
+ p->tr("hgcmHostCall failed (%Rrc)"), vrc);
+ }
+}
+
+/* static */
+RTCString GuestDnDPrivate::toFormatString(ComSafeArrayIn(IN_BSTR, formats))
+{
+ const RTCList<Utf8Str> formatList(ComSafeArrayInArg(formats));
+ RTCString strFormat;
+ for (size_t i = 0; i < formatList.size(); ++i)
+ {
+ const RTCString &f = formatList.at(i);
+ /* Only keep allowed format types. */
+ if (m_sstrAllowedMimeTypes.contains(f))
+ strFormat += f + "\r\n";
+ }
+ return strFormat;
+}
+
+/* static */
+void GuestDnDPrivate::toFormatSafeArray(const RTCString &strFormats, ComSafeArrayOut(BSTR, formats))
+{
+ RTCList<RTCString> list = strFormats.split("\r\n");
+ size_t i = 0;
+ while(i < list.size())
+ {
+ /* Only keep allowed format types. */
+ if (!m_sstrAllowedMimeTypes.contains(list.at(i)))
+ list.removeAt(i);
+ else
+ ++i;
+ }
+ /* Create a safe array out of the cleaned list. */
+ com::SafeArray<BSTR> sfaFormats(list.size());
+ for (i = 0; i < list.size(); ++i)
+ {
+ const RTCString &f = list.at(i);
+ if (m_sstrAllowedMimeTypes.contains(f))
+ {
+ Bstr bstr(f);
+ bstr.detachTo(&sfaFormats[i]);
+ }
+ }
+ sfaFormats.detachTo(ComSafeArrayOutArg(formats));
+}
+
+/* static */
+uint32_t GuestDnDPrivate::toHGCMAction(DragAndDropAction_T action)
+{
+ uint32_t a = DND_IGNORE_ACTION;
+ switch (action)
+ {
+ case DragAndDropAction_Copy: a = DND_COPY_ACTION; break;
+ case DragAndDropAction_Move: a = DND_MOVE_ACTION; break;
+ case DragAndDropAction_Link: /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */
+ case DragAndDropAction_Ignore: /* Ignored */ break;
+ default: AssertMsgFailed(("Action %u not recognized!\n", action)); break;
+ }
+ return a;
+}
+
+/* static */
+void GuestDnDPrivate::toHGCMActions(DragAndDropAction_T inDefAction, uint32_t *pOutDefAction, ComSafeArrayIn(DragAndDropAction_T, inAllowedActions), uint32_t *pOutAllowedActions)
+{
+ const com::SafeArray<DragAndDropAction_T> sfaInActions(ComSafeArrayInArg(inAllowedActions));
+
+ /* Defaults */
+ *pOutDefAction = toHGCMAction(inDefAction);;
+ *pOutAllowedActions = DND_IGNORE_ACTION;
+
+ /* First convert the allowed actions to a bit array. */
+ for (size_t i = 0; i < sfaInActions.size(); ++i)
+ *pOutAllowedActions |= toHGCMAction(sfaInActions[i]);
+
+ /* Second check if the default action is a valid action and if not so try
+ * to find an allowed action. */
+ if (isDnDIgnoreAction(*pOutDefAction))
+ {
+ if (hasDnDCopyAction(*pOutAllowedActions))
+ *pOutDefAction = DND_COPY_ACTION;
+ else if (hasDnDMoveAction(*pOutAllowedActions))
+ *pOutDefAction = DND_MOVE_ACTION;
+ }
+}
+
+/* static */
+DragAndDropAction_T GuestDnDPrivate::toMainAction(uint32_t uAction)
+{
+ /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */
+ return (isDnDCopyAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Copy :
+ isDnDMoveAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Move :
+ (DragAndDropAction_T)DragAndDropAction_Ignore);
+}
+
+/* static */
+void GuestDnDPrivate::toMainActions(uint32_t uActions, ComSafeArrayOut(DragAndDropAction_T, actions))
+{
+ /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */
+ RTCList<DragAndDropAction_T> list;
+ if (hasDnDCopyAction(uActions))
+ list.append(DragAndDropAction_Copy);
+ if (hasDnDMoveAction(uActions))
+ list.append(DragAndDropAction_Move);
+
+ com::SafeArray<DragAndDropAction_T> sfaActions(list.size());
+ for (size_t i = 0; i < list.size(); ++i)
+ sfaActions[i] = list.at(i);
+ sfaActions.detachTo(ComSafeArrayOutArg(actions));
+}
+
+GuestDnD::GuestDnD(const ComObjPtr<Guest>& pGuest)
+ : d_ptr(new GuestDnDPrivate(this, pGuest))
+{
+}
+
+GuestDnD::~GuestDnD()
+{
+ delete d_ptr;
+}
+
+HRESULT GuestDnD::dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
+{
+ DPTR(GuestDnD);
+ const ComObjPtr<Guest> &p = d->p;
+
+ /* Default is ignoring */
+ *pResultAction = DragAndDropAction_Ignore;
+
+ /* Check & convert the drag & drop actions */
+ uint32_t uDefAction = 0;
+ uint32_t uAllowedActions = 0;
+ d->toHGCMActions(defaultAction, &uDefAction, ComSafeArrayInArg(allowedActions), &uAllowedActions);
+ /* If there is no usable action, ignore this request. */
+ if (isDnDIgnoreAction(uDefAction))
+ return S_OK;
+
+ /* Make a flat data string out of the mime-type list. */
+ RTCString strFormats = d->toFormatString(ComSafeArrayInArg(formats));
+ /* If there is no valid mime-type, ignore this request. */
+ if (strFormats.isEmpty())
+ return S_OK;
+
+ HRESULT rc = S_OK;
+
+ try
+ {
+ /* Adjust the coordinates in a multi-monitor setup. */
+ d->adjustCoords(uScreenId, &uX, &uY);
+
+ VBOXHGCMSVCPARM paParms[7];
+ int i = 0;
+ paParms[i++].setUInt32(uScreenId);
+ paParms[i++].setUInt32(uX);
+ paParms[i++].setUInt32(uY);
+ paParms[i++].setUInt32(uDefAction);
+ paParms[i++].setUInt32(uAllowedActions);
+ paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+ paParms[i++].setUInt32(strFormats.length() + 1);
+
+ d->hostCall("HOST_DND_HG_EVT_ENTER",
+ DragAndDropSvc::HOST_DND_HG_EVT_ENTER,
+ i,
+ paParms);
+
+ DnDGuestResponse *pDnD = d->response();
+ /* This blocks until the request is answered (or timeout). */
+ if (pDnD->waitForGuestResponse() == VERR_TIMEOUT)
+ return S_OK;
+
+ /* Copy the response info */
+ *pResultAction = d->toMainAction(pDnD->defAction());
+ }
+ catch (HRESULT rc2)
+ {
+ rc = rc2;
+ }
+
+ return rc;
+}
+
+HRESULT GuestDnD::dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
+{
+ DPTR(GuestDnD);
+ const ComObjPtr<Guest> &p = d->p;
+
+ /* Default is ignoring */
+ *pResultAction = DragAndDropAction_Ignore;
+
+ /* Check & convert the drag & drop actions */
+ uint32_t uDefAction = 0;
+ uint32_t uAllowedActions = 0;
+ d->toHGCMActions(defaultAction, &uDefAction, ComSafeArrayInArg(allowedActions), &uAllowedActions);
+ /* If there is no usable action, ignore this request. */
+ if (isDnDIgnoreAction(uDefAction))
+ return S_OK;
+
+ /* Make a flat data string out of the mime-type list. */
+ RTCString strFormats = d->toFormatString(ComSafeArrayInArg(formats));
+ /* If there is no valid mime-type, ignore this request. */
+ if (strFormats.isEmpty())
+ return S_OK;
+
+ HRESULT rc = S_OK;
+
+ try
+ {
+ /* Adjust the coordinates in a multi-monitor setup. */
+ d->adjustCoords(uScreenId, &uX, &uY);
+
+ VBOXHGCMSVCPARM paParms[7];
+ int i = 0;
+ paParms[i++].setUInt32(uScreenId);
+ paParms[i++].setUInt32(uX);
+ paParms[i++].setUInt32(uY);
+ paParms[i++].setUInt32(uDefAction);
+ paParms[i++].setUInt32(uAllowedActions);
+ paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+ paParms[i++].setUInt32(strFormats.length() + 1);
+
+ d->hostCall("HOST_DND_HG_EVT_MOVE",
+ DragAndDropSvc::HOST_DND_HG_EVT_MOVE,
+ i,
+ paParms);
+
+ DnDGuestResponse *pDnD = d->response();
+ /* This blocks until the request is answered (or timeout). */
+ if (pDnD->waitForGuestResponse() == VERR_TIMEOUT)
+ return S_OK;
+
+ /* Copy the response info */
+ *pResultAction = d->toMainAction(pDnD->defAction());
+ }
+ catch (HRESULT rc2)
+ {
+ rc = rc2;
+ }
+
+ return rc;
+}
+
+HRESULT GuestDnD::dragHGLeave(ULONG uScreenId)
+{
+ DPTR(GuestDnD);
+ const ComObjPtr<Guest> &p = d->p;
+
+ HRESULT rc = S_OK;
+
+ try
+ {
+ d->hostCall("HOST_DND_HG_EVT_LEAVE",
+ DragAndDropSvc::HOST_DND_HG_EVT_LEAVE,
+ 0,
+ NULL);
+
+ DnDGuestResponse *pDnD = d->response();
+ /* This blocks until the request is answered (or timeout). */
+ pDnD->waitForGuestResponse();
+ }
+ catch (HRESULT rc2)
+ {
+ rc = rc2;
+ }
+
+ return rc;
+}
+
+HRESULT GuestDnD::dragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction)
+{
+ DPTR(GuestDnD);
+ const ComObjPtr<Guest> &p = d->p;
+
+ /* Default is ignoring */
+ *pResultAction = DragAndDropAction_Ignore;
+
+ /* Check & convert the drag & drop actions */
+ uint32_t uDefAction = 0;
+ uint32_t uAllowedActions = 0;
+ d->toHGCMActions(defaultAction, &uDefAction, ComSafeArrayInArg(allowedActions), &uAllowedActions);
+ /* If there is no usable action, ignore this request. */
+ if (isDnDIgnoreAction(uDefAction))
+ return S_OK;
+
+ /* Make a flat data string out of the mime-type list. */
+ RTCString strFormats = d->toFormatString(ComSafeArrayInArg(formats));
+ /* If there is no valid mime-type, ignore this request. */
+ if (strFormats.isEmpty())
+ return S_OK;
+
+ HRESULT rc = S_OK;
+
+ try
+ {
+ /* Adjust the coordinates in a multi-monitor setup. */
+ d->adjustCoords(uScreenId, &uX, &uY);
+
+ VBOXHGCMSVCPARM paParms[7];
+ int i = 0;
+ paParms[i++].setUInt32(uScreenId);
+ paParms[i++].setUInt32(uX);
+ paParms[i++].setUInt32(uY);
+ paParms[i++].setUInt32(uDefAction);
+ paParms[i++].setUInt32(uAllowedActions);
+ paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+ paParms[i++].setUInt32(strFormats.length() + 1);
+
+ d->hostCall("HOST_DND_HG_EVT_DROPPED",
+ DragAndDropSvc::HOST_DND_HG_EVT_DROPPED,
+ i,
+ paParms);
+
+ DnDGuestResponse *pDnD = d->response();
+ /* This blocks until the request is answered (or timeout). */
+ if (pDnD->waitForGuestResponse() == VERR_TIMEOUT)
+ return S_OK;
+
+ /* Copy the response info */
+ *pResultAction = d->toMainAction(pDnD->defAction());
+ Bstr(pDnD->format()).cloneTo(pstrFormat);
+ }
+ catch (HRESULT rc2)
+ {
+ rc = rc2;
+ }
+
+ return rc;
+}
+
+HRESULT GuestDnD::dragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress)
+{
+ DPTR(GuestDnD);
+ const ComObjPtr<Guest> &p = d->p;
+
+ HRESULT rc = S_OK;
+
+ try
+ {
+ Utf8Str strFormat(bstrFormat);
+ com::SafeArray<BYTE> sfaData(ComSafeArrayInArg(data));
+
+ VBOXHGCMSVCPARM paParms[5];
+ int i = 0;
+ paParms[i++].setUInt32(uScreenId);
+ paParms[i++].setPointer((void*)strFormat.c_str(), (uint32_t)strFormat.length() + 1);
+ paParms[i++].setUInt32((uint32_t)strFormat.length() + 1);
+ paParms[i++].setPointer((void*)sfaData.raw(), (uint32_t)sfaData.size());
+ paParms[i++].setUInt32((uint32_t)sfaData.size());
+
+ DnDGuestResponse *pDnD = d->response();
+ /* Reset any old progress status. */
+ pDnD->resetProgress(p);
+
+ d->hostCall("HOST_DND_HG_SND_DATA",
+ DragAndDropSvc::HOST_DND_HG_SND_DATA,
+ i,
+ paParms);
+
+ /* Query the progress object to the caller. */
+ pDnD->queryProgressTo(ppProgress);
+ }
+ catch (HRESULT rc2)
+ {
+ rc = rc2;
+ }
+
+ return rc;
+}
+
+# ifdef VBOX_WITH_DRAG_AND_DROP_GH
+HRESULT GuestDnD::dragGHPending(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction)
+{
+ DPTR(GuestDnD);
+ const ComObjPtr<Guest> &p = d->p;
+
+ /* Default is ignoring */
+ *pDefaultAction = DragAndDropAction_Ignore;
+
+ HRESULT rc = S_OK;
+
+ try
+ {
+ VBOXHGCMSVCPARM paParms[1];
+ int i = 0;
+ paParms[i++].setUInt32(uScreenId);
+
+ d->hostCall("HOST_DND_GH_REQ_PENDING",
+ DragAndDropSvc::HOST_DND_GH_REQ_PENDING,
+ i,
+ paParms);
+
+ DnDGuestResponse *pDnD = d->response();
+ /* This blocks until the request is answered (or timeout). */
+ if (pDnD->waitForGuestResponse() == VERR_TIMEOUT)
+ return S_OK;
+
+ if (isDnDIgnoreAction(pDnD->defAction()))
+ return S_OK;
+
+ /* Fetch the default action to use. */
+ *pDefaultAction = d->toMainAction(pDnD->defAction());
+ /* Convert the formats strings to a vector of strings. */
+ d->toFormatSafeArray(pDnD->format(), ComSafeArrayOutArg(formats));
+ /* Convert the action bit field to a vector of actions. */
+ d->toMainActions(pDnD->allActions(), ComSafeArrayOutArg(allowedActions));
+ }
+ catch (HRESULT rc2)
+ {
+ rc = rc2;
+ }
+
+ return rc;
+}
+
+HRESULT GuestDnD::dragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, IProgress **ppProgress)
+{
+ DPTR(GuestDnD);
+ const ComObjPtr<Guest> &p = d->p;
+
+ Utf8Str strFormat(bstrFormat);
+ HRESULT rc = S_OK;
+
+ uint32_t uAction = d->toHGCMAction(action);
+ /* If there is no usable action, ignore this request. */
+ if (isDnDIgnoreAction(uAction))
+ return S_OK;
+
+ try
+ {
+ VBOXHGCMSVCPARM paParms[3];
+ int i = 0;
+ paParms[i++].setPointer((void*)strFormat.c_str(), (uint32_t)strFormat.length() + 1);
+ paParms[i++].setUInt32((uint32_t)strFormat.length() + 1);
+ paParms[i++].setUInt32(uAction);
+
+ DnDGuestResponse *pDnD = d->response();
+ /* Reset any old data and the progress status. */
+ pDnD->resetData();
+ pDnD->resetProgress(p);
+
+ d->hostCall("HOST_DND_GH_EVT_DROPPED",
+ DragAndDropSvc::HOST_DND_GH_EVT_DROPPED,
+ i,
+ paParms);
+
+ /* Query the progress object to the caller. */
+ pDnD->queryProgressTo(ppProgress);
+ }
+ catch (HRESULT rc2)
+ {
+ rc = rc2;
+ }
+
+ return rc;
+}
+
+HRESULT GuestDnD::dragGHGetData(ComSafeArrayOut(BYTE, data))
+{
+ DPTR(GuestDnD);
+ const ComObjPtr<Guest> &p = d->p;
+
+ HRESULT rc = S_OK;
+
+ DnDGuestResponse *pDnD = d->response();
+ /* Is there data at all? */
+ if (pDnD->hasData())
+ {
+ /* Copy the data into an safe array of bytes. */
+ void *pvData = 0;
+ uint32_t cbData = 0;
+ pDnD->data(&pvData, &cbData);
+ com::SafeArray<BYTE> sfaData(cbData);
+ memcpy(sfaData.raw(), pvData, cbData);
+ sfaData.detachTo(ComSafeArrayOutArg(data));
+ /* Delete the data. */
+ pDnD->resetData();
+ }
+ else
+ rc = VBOX_E_INVALID_OBJECT_STATE;
+
+ return rc;
+}
+
+# endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+
+DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms)
+{
+ ComObjPtr<Guest> pGuest = reinterpret_cast<Guest*>(pvExtension);
+ if (!pGuest->m_pGuestDnD)
+ return VINF_SUCCESS;
+
+ GuestDnDPrivate *d = static_cast<GuestDnDPrivate*>(pGuest->m_pGuestDnD->d_ptr);
+ const ComObjPtr<Guest> &p = d->p;
+
+ DnDGuestResponse *pDnD = d->response();
+ if (pDnD == NULL)
+ return VERR_INVALID_PARAMETER;
+
+ int rc = VINF_SUCCESS;
+ switch (u32Function)
+ {
+ case DragAndDropSvc::GUEST_DND_HG_ACK_OP:
+ {
+ DragAndDropSvc::PVBOXDNDCBHGACKOPDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGACKOPDATA>(pvParms);
+ AssertPtr(pCBData);
+ AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGACKOPDATA) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+ pDnD->setDefAction(pCBData->uAction);
+ rc = pDnD->notifyAboutGuestResponse();
+ break;
+ }
+ case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:
+ {
+ DragAndDropSvc::PVBOXDNDCBHGREQDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGREQDATADATA>(pvParms);
+ AssertPtr(pCBData);
+ AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGREQDATADATA) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+ pDnD->setFormat(pCBData->pszFormat);
+ rc = pDnD->notifyAboutGuestResponse();
+ break;
+ }
+ case DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS:
+ {
+ DragAndDropSvc::PVBOXDNDCBHGEVTPROGRESSDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGEVTPROGRESSDATA>(pvParms);
+ AssertPtr(pCBData);
+ AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+ rc = pDnD->setProgress(pCBData->uPercentage, pCBData->uState);
+ break;
+ }
+#ifdef VBOX_WITH_DRAG_AND_DROP_GH
+ case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING:
+ {
+ DragAndDropSvc::PVBOXDNDCBGHACKPENDINGDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBGHACKPENDINGDATA>(pvParms);
+ AssertPtr(pCBData);
+ AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+ pDnD->setFormat(pCBData->pszFormat);
+ pDnD->setDefAction(pCBData->uDefAction);
+ pDnD->setAllActions(pCBData->uAllActions);
+ rc = pDnD->notifyAboutGuestResponse();
+ break;
+ }
+ case DragAndDropSvc::GUEST_DND_GH_SND_DATA:
+ {
+ DragAndDropSvc::PVBOXDNDCBSNDDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDATADATA>(pvParms);
+ AssertPtr(pCBData);
+ AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDATADATA) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+ uint32_t cbCurSize = 0;
+ pDnD->addData(pCBData->pvData, pCBData->cbData, &cbCurSize);
+ rc = pDnD->setProgress(100.0 / pCBData->cbAllSize * cbCurSize, (pCBData->cbAllSize == cbCurSize ? DragAndDropSvc::DND_PROGRESS_COMPLETE : DragAndDropSvc::DND_PROGRESS_RUNNING));
+ /* Todo: for now we instantly confirm the cancel. Check if the
+ * guest should first clean up stuff itself and than really confirm
+ * the cancel request by an extra message. */
+ if (rc == VERR_CANCELLED)
+ pDnD->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED);
+ break;
+ }
+ case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
+ {
+ DragAndDropSvc::PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBEVTERRORDATA>(pvParms);
+ AssertPtr(pCBData);
+ AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);
+ AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+ /* Cleanup */
+ pDnD->resetData();
+ rc = pDnD->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc);
+ break;
+ }
+#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+ default: AssertMsgFailedReturn(("Function %u not recognized!\n", u32Function), VERR_INVALID_PARAMETER); break;
+ }
+
+ return rc;
+}
+
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+
diff --git a/src/VBox/Main/src-client/GuestFileImpl.cpp b/src/VBox/Main/src-client/GuestFileImpl.cpp
new file mode 100644
index 000000000..19afbcc24
--- /dev/null
+++ b/src/VBox/Main/src-client/GuestFileImpl.cpp
@@ -0,0 +1,339 @@
+
+/* $Id: GuestFileImpl.cpp $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "GuestFileImpl.h"
+#include "GuestSessionImpl.h"
+#include "GuestCtrlImplPrivate.h"
+
+#include "Global.h"
+#include "AutoCaller.h"
+
+#include <VBox/com/array.h>
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
+#include <VBox/log.h>
+
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR(GuestFile)
+
+HRESULT GuestFile::FinalConstruct(void)
+{
+ LogFlowThisFunc(("\n"));
+ return BaseFinalConstruct();
+}
+
+void GuestFile::FinalRelease(void)
+{
+ LogFlowThisFuncEnter();
+ uninit();
+ BaseFinalRelease();
+ LogFlowThisFuncLeave();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+int GuestFile::init(GuestSession *pSession, const Utf8Str &strPath,
+ const Utf8Str &strOpenMode, const Utf8Str &strDisposition, uint32_t uCreationMode,
+ int64_t iOffset, int *pGuestRc)
+{
+ /* Enclose the state transition NotReady->InInit->Ready. */
+ AutoInitSpan autoInitSpan(this);
+ AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+ mData.mSession = pSession;
+ mData.mCreationMode = uCreationMode;
+ mData.mDisposition = GuestFile::getDispositionFromString(strDisposition);
+ mData.mFileName = strPath;
+ mData.mInitialSize = 0;
+ mData.mOpenMode = GuestFile::getOpenModeFromString(strOpenMode);
+ mData.mOffset = iOffset;
+
+ /** @todo Validate parameters! */
+ /** @todo Implement guest side file handling! */
+
+ /* Confirm a successful initialization when it's the case. */
+ autoInitSpan.setSucceeded();
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called from FinalRelease().
+ */
+void GuestFile::uninit(void)
+{
+ LogFlowThisFunc(("\n"));
+
+ /* Enclose the state transition Ready->InUninit->NotReady. */
+ AutoUninitSpan autoUninitSpan(this);
+ if (autoUninitSpan.uninitDone())
+ return;
+
+ LogFlowThisFuncLeave();
+}
+
+// implementation of public getters/setters for attributes
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestFile::COMGETTER(CreationMode)(ULONG *aCreationMode)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aCreationMode);
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aCreationMode = mData.mCreationMode;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::COMGETTER(Disposition)(ULONG *aDisposition)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aDisposition);
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aDisposition = mData.mDisposition;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::COMGETTER(FileName)(BSTR *aFileName)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aFileName);
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mFileName.cloneTo(aFileName);
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::COMGETTER(InitialSize)(LONG64 *aInitialSize)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aInitialSize);
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aInitialSize = mData.mInitialSize;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::COMGETTER(Offset)(LONG64 *aOffset)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aOffset);
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aOffset = mData.mOffset;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::COMGETTER(OpenMode)(ULONG *aOpenMode)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aOpenMode);
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aOpenMode = mData.mOpenMode;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+// private methods
+/////////////////////////////////////////////////////////////////////////////
+
+/* static */
+uint32_t GuestFile::getDispositionFromString(const Utf8Str &strDisposition)
+{
+ return 0; /** @todo Implement me! */
+}
+
+/* static */
+uint32_t GuestFile::getOpenModeFromString(const Utf8Str &strOpenMode)
+{
+ return 0; /** @todo Implement me! */
+}
+
+// implementation of public methods
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestFile::Close(void)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AssertPtr(mData.mSession);
+ int rc = mData.mSession->fileRemoveFromList(this);
+
+ /*
+ * Release autocaller before calling uninit.
+ */
+ autoCaller.release();
+
+ uninit();
+
+ LogFlowFuncLeaveRC(rc);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::QueryInfo(IFsObjInfo **aInfo)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::Read(ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::ReadAt(LONG64 aOffset, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::Seek(LONG64 aOffset, FileSeekType_T aType)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::SetACL(IN_BSTR aACL)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::Write(ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFile::WriteAt(LONG64 aOffset, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
diff --git a/src/VBox/Main/src-client/GuestFsObjInfoImpl.cpp b/src/VBox/Main/src-client/GuestFsObjInfoImpl.cpp
new file mode 100644
index 000000000..99219da77
--- /dev/null
+++ b/src/VBox/Main/src-client/GuestFsObjInfoImpl.cpp
@@ -0,0 +1,412 @@
+
+/* $Id: GuestFsObjInfoImpl.cpp $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "GuestFsObjInfoImpl.h"
+#include "GuestCtrlImplPrivate.h"
+
+#include "Global.h"
+#include "AutoCaller.h"
+
+#include <VBox/com/array.h>
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
+#include <VBox/log.h>
+
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR(GuestFsObjInfo)
+
+HRESULT GuestFsObjInfo::FinalConstruct(void)
+{
+ LogFlowThisFunc(("\n"));
+ return BaseFinalConstruct();
+}
+
+void GuestFsObjInfo::FinalRelease(void)
+{
+ LogFlowThisFuncEnter();
+ uninit();
+ BaseFinalRelease();
+ LogFlowThisFuncLeave();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+int GuestFsObjInfo::init(const GuestFsObjData &objData)
+{
+ LogFlowThisFuncEnter();
+
+ /* Enclose the state transition NotReady->InInit->Ready. */
+ AutoInitSpan autoInitSpan(this);
+ AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+ mData = objData;
+
+ /* Confirm a successful initialization when it's the case. */
+ autoInitSpan.setSucceeded();
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called from FinalRelease().
+ */
+void GuestFsObjInfo::uninit(void)
+{
+ LogFlowThisFunc(("\n"));
+
+ /* Enclose the state transition Ready->InUninit->NotReady. */
+ AutoUninitSpan autoUninitSpan(this);
+ if (autoUninitSpan.uninitDone())
+ return;
+}
+
+// implementation of public getters/setters for attributes
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(AccessTime)(LONG64 *aAccessTime)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aAccessTime);
+
+ *aAccessTime = mData.mAccessTime;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(AllocatedSize)(LONG64 *aAllocatedSize)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aAllocatedSize);
+
+ *aAllocatedSize = mData.mAllocatedSize;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(BirthTime)(LONG64 *aBirthTime)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aBirthTime);
+
+ *aBirthTime = mData.mBirthTime;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(ChangeTime)(LONG64 *aChangeTime)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aChangeTime);
+
+ *aChangeTime = mData.mChangeTime;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(DeviceNumber)(ULONG *aDeviceNumber)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aDeviceNumber);
+
+ *aDeviceNumber = mData.mDeviceNumber;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(FileAttributes)(BSTR *aAttributes)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aAttributes);
+
+ mData.mFileAttrs.cloneTo(aAttributes);
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(GenerationId)(ULONG *aGenerationId)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aGenerationId);
+
+ *aGenerationId = mData.mGenerationID;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(GID)(ULONG *aGID)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aGID);
+
+ *aGID = mData.mGID;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(GroupName)(BSTR *aGroupName)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aGroupName);
+
+ mData.mGroupName.cloneTo(aGroupName);
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(HardLinks)(ULONG *aHardLinks)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aHardLinks);
+
+ *aHardLinks = mData.mNumHardLinks;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(ModificationTime)(LONG64 *aModificationTime)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aModificationTime);
+
+ *aModificationTime = mData.mModificationTime;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(Name)(BSTR *aName)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aName);
+
+ mData.mName.cloneTo(aName);
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(NodeId)(LONG64 *aNodeId)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aNodeId);
+
+ *aNodeId = mData.mNodeID;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(NodeIdDevice)(ULONG *aNodeIdDevice)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aNodeIdDevice);
+
+ *aNodeIdDevice = mData.mNodeIDDevice;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(ObjectSize)(LONG64 *aObjectSize)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aObjectSize);
+
+ *aObjectSize = mData.mObjectSize;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(Type)(FsObjType_T *aType)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aType);
+
+ *aType = mData.mType;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(UID)(ULONG *aUID)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aUID);
+
+ *aUID = mData.mUID;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(UserFlags)(ULONG *aUserFlags)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aUserFlags);
+
+ *aUserFlags = mData.mUserFlags;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(UserName)(BSTR *aUserName)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aUserName);
+
+ mData.mUserName.cloneTo(aUserName);
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestFsObjInfo::COMGETTER(ACL)(BSTR *aACL)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ CheckComArgOutPointerValid(aACL);
+
+ mData.mACL.cloneTo(aACL);
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
diff --git a/src/VBox/Main/src-client/GuestImpl.cpp b/src/VBox/Main/src-client/GuestImpl.cpp
index 72cd9c4a0..7ebdf53b7 100644
--- a/src/VBox/Main/src-client/GuestImpl.cpp
+++ b/src/VBox/Main/src-client/GuestImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -16,10 +16,14 @@
*/
#include "GuestImpl.h"
+#include "GuestSessionImpl.h"
#include "Global.h"
#include "ConsoleImpl.h"
#include "ProgressImpl.h"
+#ifdef VBOX_WITH_DRAG_AND_DROP
+# include "GuestDnDImpl.h"
+#endif
#include "VMMDev.h"
#include "AutoCaller.h"
@@ -27,11 +31,9 @@
#include "Performance.h"
#include <VBox/VMMDev.h>
-#ifdef VBOX_WITH_GUEST_CONTROL
-# include <VBox/com/array.h>
-# include <VBox/com/ErrorInfo.h>
-#endif
#include <iprt/cpp/utils.h>
+#include <iprt/ctype.h>
+#include <iprt/stream.h>
#include <iprt/timer.h>
#include <VBox/vmm/pgm.h>
#include <VBox/version.h>
@@ -42,7 +44,7 @@
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
-DEFINE_EMPTY_CTOR_DTOR (Guest)
+DEFINE_EMPTY_CTOR_DTOR(Guest)
HRESULT Guest::FinalConstruct()
{
@@ -51,7 +53,7 @@ HRESULT Guest::FinalConstruct()
void Guest::FinalRelease()
{
- uninit ();
+ uninit();
BaseFinalRelease();
}
@@ -94,22 +96,28 @@ HRESULT Guest::init(Console *aParent)
mCollectVMMStats = false;
/* Clear statistics. */
+ mNetStatRx = mNetStatTx = 0;
+ mNetStatLastTs = RTTimeNanoTS();
for (unsigned i = 0 ; i < GUESTSTATTYPE_MAX; i++)
mCurrentGuestStat[i] = 0;
- mGuestValidStats = pm::GUESTSTATMASK_NONE;
+ mVmValidStats = pm::VMSTATMASK_NONE;
mMagic = GUEST_MAGIC;
- int vrc = RTTimerLRCreate (&mStatTimer, 1000 /* ms */,
- &Guest::staticUpdateStats, this);
- AssertMsgRC (vrc, ("Failed to create guest statistics "
- "update timer(%Rra)\n", vrc));
+ int vrc = RTTimerLRCreate(&mStatTimer, 1000 /* ms */,
+ &Guest::staticUpdateStats, this);
+ AssertMsgRC(vrc, ("Failed to create guest statistics update timer(%Rra)\n", vrc));
-#ifdef VBOX_WITH_GUEST_CONTROL
- /* Init the context ID counter at 1000. */
- mNextContextID = 1000;
- /* Init the host PID counter. */
- mNextHostPID = 0;
+ try
+ {
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ m_pGuestDnD = new GuestDnD(this);
+ AssertPtr(m_pGuestDnD);
#endif
+ }
+ catch(std::bad_alloc &)
+ {
+ return E_OUTOFMEMORY;
+ }
return S_OK;
}
@@ -127,54 +135,97 @@ void Guest::uninit()
if (autoUninitSpan.uninitDone())
return;
+ /* Destroy stat update timer */
+ int vrc = RTTimerLRDestroy(mStatTimer);
+ AssertMsgRC(vrc, ("Failed to create guest statistics update timer(%Rra)\n", vrc));
+ mStatTimer = NULL;
+ mMagic = 0;
+
#ifdef VBOX_WITH_GUEST_CONTROL
- /* Scope write lock as much as possible. */
+ LogFlowThisFunc(("Closing sessions (%RU64 total)\n",
+ mData.mGuestSessions.size()));
+ GuestSessions::iterator itSessions = mData.mGuestSessions.begin();
+ while (itSessions != mData.mGuestSessions.end())
{
- /*
- * Cleanup must be done *before* AutoUninitSpan to cancel all
- * all outstanding waits in API functions (which hold AutoCaller
- * ref counts).
- */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* Notify left over callbacks that we are about to shutdown ... */
- CallbackMapIter it;
- for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
- {
- int rc2 = callbackNotifyEx(it->first, VERR_CANCELLED,
- Guest::tr("VM is shutting down, canceling uncompleted guest requests ..."));
- AssertRC(rc2);
- }
-
- /* Destroy left over callback data. */
- for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
- callbackDestroy(it->first);
-
- /* Clear process map (remove all callbacks). */
- mGuestProcessMap.clear();
+#ifdef DEBUG
+ ULONG cRefs = itSessions->second->AddRef();
+ LogFlowThisFunc(("pSession=%p, cRefs=%RU32\n", (GuestSession *)itSessions->second, cRefs > 0 ? cRefs - 1 : 0));
+ itSessions->second->Release();
+#endif
+ itSessions->second->uninit();
+ itSessions++;
}
+ mData.mGuestSessions.clear();
#endif
- /* Destroy stat update timer */
- int vrc = RTTimerLRDestroy (mStatTimer);
- AssertMsgRC (vrc, ("Failed to create guest statistics "
- "update timer(%Rra)\n", vrc));
- mStatTimer = NULL;
- mMagic = 0;
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ if (m_pGuestDnD)
+ {
+ delete m_pGuestDnD;
+ m_pGuestDnD = NULL;
+ }
+#endif
unconst(mParent) = NULL;
+
+ LogFlowFuncLeave();
}
/* static */
void Guest::staticUpdateStats(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick)
{
- AssertReturnVoid (pvUser != NULL);
- Guest *guest = static_cast <Guest *> (pvUser);
+ AssertReturnVoid(pvUser != NULL);
+ Guest *guest = static_cast<Guest *>(pvUser);
Assert(guest->mMagic == GUEST_MAGIC);
if (guest->mMagic == GUEST_MAGIC)
guest->updateStats(iTick);
- NOREF (hTimerLR);
+ NOREF(hTimerLR);
+}
+
+/* static */
+int Guest::staticEnumStatsCallback(const char *pszName, STAMTYPE enmType, void *pvSample, STAMUNIT enmUnit,
+ STAMVISIBILITY enmVisiblity, const char *pszDesc, void *pvUser)
+{
+ PSTAMCOUNTER pCnt = (PSTAMCOUNTER)pvSample;
+ char *pszEnd = strrchr((char*)pszName, '/');
+ if (pszEnd)
+ {
+ bool fRx;
+ uint8_t uInstance = 0;
+
+ switch (pszEnd[1])
+ {
+ case 'R':
+ fRx = true;
+ break;
+ case 'T':
+ fRx = false;
+ break;
+ default:
+ LogRel(("Failed to parse the name of network stat counter (unknown counter): %s\n", pszName));
+ return VINF_SUCCESS;
+ }
+ do
+ --pszEnd;
+ while (pszEnd > pszName && RT_C_IS_DIGIT(*pszEnd));
+ if (RT_SUCCESS(RTStrToUInt8Ex(pszEnd + 1, NULL, 10, &uInstance)))
+ {
+ Guest *pGuest = (Guest *)pvUser;
+ LogFlowFunc(("%s i=%u d=%s %llu %s\n", pszName, uInstance, fRx ? "RX" : "TX",
+ pCnt->c, STAMR3GetUnit(enmUnit)));
+ if (fRx)
+ pGuest->mNetStatRx += pCnt->c;
+ else
+ pGuest->mNetStatTx += pCnt->c;
+ }
+ else
+ LogRel(("Failed to extract the device instance from the name of network stat counter: %s\n", pszEnd));
+ }
+ else
+ LogRel(("Failed to parse the name of network stat counter (no slash): %s\n", pszName));
+
+ return VINF_SUCCESS;
}
void Guest::updateStats(uint64_t iTick)
@@ -184,13 +235,15 @@ void Guest::updateStats(uint64_t iTick)
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ ULONG uNetStatRx = 0;
+ ULONG uNetStatTx = 0;
ULONG aGuestStats[GUESTSTATTYPE_MAX];
RT_ZERO(aGuestStats);
- ULONG validStats = mGuestValidStats;
+ ULONG validStats = mVmValidStats;
/* Check if we have anything to report */
if (validStats)
{
- mGuestValidStats = pm::GUESTSTATMASK_NONE;
+ mVmValidStats = pm::VMSTATMASK_NONE;
memcpy(aGuestStats, mCurrentGuestStat, sizeof(aGuestStats));
}
alock.release();
@@ -208,7 +261,7 @@ void Guest::updateStats(uint64_t iTick)
uSharedMem = 0;
uZeroMem = 0;
- Console::SafeVMPtr pVM (mParent);
+ Console::SafeVMPtr pVM(mParent);
if (pVM.isOk())
{
int rc;
@@ -223,7 +276,7 @@ void Guest::updateStats(uint64_t iTick)
rc = PGMR3QueryMemoryStats(pVM.raw(), &uTotalMem, &uPrivateMem, &uSharedMem, &uZeroMem);
if (rc == VINF_SUCCESS)
{
- validStats |= pm::GUESTSTATMASK_MEMSHARED;
+ validStats |= pm::VMSTATMASK_GUEST_MEMSHARED;
}
}
@@ -233,28 +286,43 @@ void Guest::updateStats(uint64_t iTick)
AssertRC(rc);
if (rc == VINF_SUCCESS)
{
- validStats |= pm::GUESTSTATMASK_ALLOCVMM|pm::GUESTSTATMASK_FREEVMM|
- pm::GUESTSTATMASK_BALOONVMM|pm::GUESTSTATMASK_SHAREDVMM;
+ validStats |=
+ pm::VMSTATMASK_VMM_ALLOC | pm::VMSTATMASK_VMM_FREE |
+ pm::VMSTATMASK_VMM_BALOON | pm::VMSTATMASK_VMM_SHARED;
}
}
+ uint64_t uRxPrev = mNetStatRx;
+ uint64_t uTxPrev = mNetStatTx;
+ mNetStatRx = mNetStatTx = 0;
+ rc = STAMR3Enum(pVM, "*/ReceiveBytes|*/TransmitBytes", staticEnumStatsCallback, this);
+ uint64_t uTsNow = RTTimeNanoTS();
+ uint64_t uTimePassed = uTsNow - mNetStatLastTs;
+ mNetStatLastTs = uTsNow;
+ uNetStatRx = (ULONG)((mNetStatRx - uRxPrev) * 1000000 / (uTimePassed / 1000)); /* in bytes per second */
+ uNetStatTx = (ULONG)((mNetStatTx - uTxPrev) * 1000000 / (uTimePassed / 1000)); /* in bytes per second */
+ LogFlowThisFunc(("Net Rx=%llu Tx=%llu Ts=%llu Delta=%llu\n", mNetStatRx, mNetStatTx, uTsNow, uTimePassed));
+ AssertRC(rc);
+ validStats |= pm::VMSTATMASK_NET_RX | pm::VMSTATMASK_NET_TX;
}
- mParent->reportGuestStatistics(validStats,
- aGuestStats[GUESTSTATTYPE_CPUUSER],
- aGuestStats[GUESTSTATTYPE_CPUKERNEL],
- aGuestStats[GUESTSTATTYPE_CPUIDLE],
- /* Convert the units for RAM usage stats: page (4K) -> 1KB units */
- mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K),
- mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K),
- mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K),
- (ULONG)(uSharedMem / _1K), /* bytes -> KB */
- mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K),
- mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K),
- (ULONG)(uAllocTotal / _1K), /* bytes -> KB */
- (ULONG)(uFreeTotal / _1K),
- (ULONG)(uBalloonedTotal / _1K),
- (ULONG)(uSharedTotal / _1K));
+ mParent->reportVmStatistics(validStats,
+ aGuestStats[GUESTSTATTYPE_CPUUSER],
+ aGuestStats[GUESTSTATTYPE_CPUKERNEL],
+ aGuestStats[GUESTSTATTYPE_CPUIDLE],
+ /* Convert the units for RAM usage stats: page (4K) -> 1KB units */
+ mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K),
+ mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K),
+ mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K),
+ (ULONG)(uSharedMem / _1K), /* bytes -> KB */
+ mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K),
+ mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K),
+ (ULONG)(uAllocTotal / _1K), /* bytes -> KB */
+ (ULONG)(uFreeTotal / _1K),
+ (ULONG)(uBalloonedTotal / _1K),
+ (ULONG)(uSharedTotal / _1K),
+ uNetStatRx,
+ uNetStatTx);
}
// IGuest properties
@@ -282,7 +350,7 @@ STDMETHODIMP Guest::COMGETTER(OSTypeId)(BSTR *a_pbstrOSTypeId)
return hrc;
}
-STDMETHODIMP Guest::COMGETTER(AdditionsRunLevel) (AdditionsRunLevelType_T *aRunLevel)
+STDMETHODIMP Guest::COMGETTER(AdditionsRunLevel)(AdditionsRunLevelType_T *aRunLevel)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -307,16 +375,9 @@ STDMETHODIMP Guest::COMGETTER(AdditionsVersion)(BSTR *a_pbstrAdditionsVersion)
/*
* Return the ReportGuestInfo2 version info if available.
*/
- if (!mData.mAdditionsVersionNew.isEmpty())
- {
- /* Since we don't have the API in 4.1 to return a separate revision, we
- * need to ship the revision as part of the version string, separated with
- * the "r" prefix. */
- Bstr strVersion = mData.mAdditionsRevision
- ? BstrFmt("%lsr%u", mData.mAdditionsVersionNew.raw(), mData.mAdditionsRevision)
- : BstrFmt("%ls", mData.mAdditionsVersionNew.raw());
- strVersion.cloneTo(a_pbstrAdditionsVersion);
- }
+ if ( !mData.mAdditionsVersionNew.isEmpty()
+ || mData.mAdditionsRunLevel <= AdditionsRunLevelType_None)
+ mData.mAdditionsVersionNew.cloneTo(a_pbstrAdditionsVersion);
else
{
/*
@@ -354,7 +415,65 @@ STDMETHODIMP Guest::COMGETTER(AdditionsVersion)(BSTR *a_pbstrAdditionsVersion)
return hrc;
}
-STDMETHODIMP Guest::COMGETTER(Facilities)(ComSafeArrayOut(IAdditionsFacility*, aFacilities))
+STDMETHODIMP Guest::COMGETTER(AdditionsRevision)(ULONG *a_puAdditionsRevision)
+{
+ CheckComArgOutPointerValid(a_puAdditionsRevision);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ /*
+ * Return the ReportGuestInfo2 version info if available.
+ */
+ if ( !mData.mAdditionsVersionNew.isEmpty()
+ || mData.mAdditionsRunLevel <= AdditionsRunLevelType_None)
+ *a_puAdditionsRevision = mData.mAdditionsRevision;
+ else
+ {
+ /*
+ * If we're running older guest additions (< 3.2.0) try get it from
+ * the guest properties. Detected switched around Version and
+ * Revision in early 3.1.x releases (see r57115).
+ */
+ ComPtr<IMachine> ptrMachine = mParent->machine();
+ alock.release(); /* No need to hold this during the IPC fun. */
+
+ Bstr bstr;
+ hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Revision").raw(), bstr.asOutParam());
+ if (SUCCEEDED(hrc))
+ {
+ Utf8Str str(bstr);
+ uint32_t uRevision;
+ int vrc = RTStrToUInt32Full(str.c_str(), 0, &uRevision);
+ if (vrc != VINF_SUCCESS && str.count('.') == 2)
+ {
+ hrc = ptrMachine->GetGuestPropertyValue(Bstr("/VirtualBox/GuestAdd/Version").raw(), bstr.asOutParam());
+ if (SUCCEEDED(hrc))
+ {
+ str = bstr;
+ vrc = RTStrToUInt32Full(str.c_str(), 0, &uRevision);
+ }
+ }
+ if (vrc == VINF_SUCCESS)
+ *a_puAdditionsRevision = uRevision;
+ else
+ hrc = VBOX_E_IPRT_ERROR;
+ }
+ if (FAILED(hrc))
+ {
+ /* Return 0 if we don't know. */
+ *a_puAdditionsRevision = 0;
+ hrc = S_OK;
+ }
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP Guest::COMGETTER(Facilities)(ComSafeArrayOut(IAdditionsFacility *, aFacilities))
{
CheckComArgOutSafeArrayPointerValid(aFacilities);
@@ -369,6 +488,21 @@ STDMETHODIMP Guest::COMGETTER(Facilities)(ComSafeArrayOut(IAdditionsFacility*, a
return S_OK;
}
+STDMETHODIMP Guest::COMGETTER(Sessions)(ComSafeArrayOut(IGuestSession *, aSessions))
+{
+ CheckComArgOutSafeArrayPointerValid(aSessions);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ SafeIfaceArray<IGuestSession> collection(mData.mGuestSessions);
+ collection.detachTo(ComSafeArrayOutArg(aSessions));
+
+ return S_OK;
+}
+
BOOL Guest::isPageFusionEnabled()
{
AutoCaller autoCaller(this);
@@ -551,15 +685,15 @@ HRESULT Guest::setStatistic(ULONG aCpuId, GUESTSTATTYPE enmType, ULONG aVal)
{
static ULONG indexToPerfMask[] =
{
- pm::GUESTSTATMASK_CPUUSER,
- pm::GUESTSTATMASK_CPUKERNEL,
- pm::GUESTSTATMASK_CPUIDLE,
- pm::GUESTSTATMASK_MEMTOTAL,
- pm::GUESTSTATMASK_MEMFREE,
- pm::GUESTSTATMASK_MEMBALLOON,
- pm::GUESTSTATMASK_MEMCACHE,
- pm::GUESTSTATMASK_PAGETOTAL,
- pm::GUESTSTATMASK_NONE
+ pm::VMSTATMASK_GUEST_CPUUSER,
+ pm::VMSTATMASK_GUEST_CPUKERNEL,
+ pm::VMSTATMASK_GUEST_CPUIDLE,
+ pm::VMSTATMASK_GUEST_MEMTOTAL,
+ pm::VMSTATMASK_GUEST_MEMFREE,
+ pm::VMSTATMASK_GUEST_MEMBALLOON,
+ pm::VMSTATMASK_GUEST_MEMCACHE,
+ pm::VMSTATMASK_GUEST_PAGETOTAL,
+ pm::VMSTATMASK_NONE
};
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -570,7 +704,7 @@ HRESULT Guest::setStatistic(ULONG aCpuId, GUESTSTATTYPE enmType, ULONG aVal)
return E_INVALIDARG;
mCurrentGuestStat[enmType] = aVal;
- mGuestValidStats |= indexToPerfMask[enmType];
+ mVmValidStats |= indexToPerfMask[enmType];
return S_OK;
}
@@ -674,6 +808,135 @@ STDMETHODIMP Guest::SetCredentials(IN_BSTR aUserName, IN_BSTR aPassword,
tr("VMM device is not available (is the VM running?)"));
}
+STDMETHODIMP Guest::DragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
+{
+ /* Input validation */
+ CheckComArgSafeArrayNotNull(allowedActions);
+ CheckComArgSafeArrayNotNull(formats);
+ CheckComArgOutPointerValid(pResultAction);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ return m_pGuestDnD->dragHGEnter(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pResultAction);
+#else /* VBOX_WITH_DRAG_AND_DROP */
+ ReturnComNotImplemented();
+#endif /* !VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP Guest::DragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
+{
+ /* Input validation */
+ CheckComArgSafeArrayNotNull(allowedActions);
+ CheckComArgSafeArrayNotNull(formats);
+ CheckComArgOutPointerValid(pResultAction);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ return m_pGuestDnD->dragHGMove(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pResultAction);
+#else /* VBOX_WITH_DRAG_AND_DROP */
+ ReturnComNotImplemented();
+#endif /* !VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP Guest::DragHGLeave(ULONG uScreenId)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ return m_pGuestDnD->dragHGLeave(uScreenId);
+#else /* VBOX_WITH_DRAG_AND_DROP */
+ ReturnComNotImplemented();
+#endif /* !VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP Guest::DragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction)
+{
+ /* Input validation */
+ CheckComArgSafeArrayNotNull(allowedActions);
+ CheckComArgSafeArrayNotNull(formats);
+ CheckComArgOutPointerValid(pstrFormat);
+ CheckComArgOutPointerValid(pResultAction);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ return m_pGuestDnD->dragHGDrop(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pstrFormat, pResultAction);
+#else /* VBOX_WITH_DRAG_AND_DROP */
+ ReturnComNotImplemented();
+#endif /* !VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP Guest::DragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress)
+{
+ /* Input validation */
+ CheckComArgStrNotEmptyOrNull(bstrFormat);
+ CheckComArgSafeArrayNotNull(data);
+ CheckComArgOutPointerValid(ppProgress);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ return m_pGuestDnD->dragHGPutData(uScreenId, bstrFormat, ComSafeArrayInArg(data), ppProgress);
+#else /* VBOX_WITH_DRAG_AND_DROP */
+ ReturnComNotImplemented();
+#endif /* !VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP Guest::DragGHPending(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction)
+{
+ /* Input validation */
+ CheckComArgSafeArrayNotNull(formats);
+ CheckComArgSafeArrayNotNull(allowedActions);
+ CheckComArgOutPointerValid(pDefaultAction);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#if defined(VBOX_WITH_DRAG_AND_DROP) && defined(VBOX_WITH_DRAG_AND_DROP_GH)
+ return m_pGuestDnD->dragGHPending(uScreenId, ComSafeArrayOutArg(formats), ComSafeArrayOutArg(allowedActions), pDefaultAction);
+#else /* VBOX_WITH_DRAG_AND_DROP */
+ ReturnComNotImplemented();
+#endif /* !VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP Guest::DragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, IProgress **ppProgress)
+{
+ /* Input validation */
+ CheckComArgStrNotEmptyOrNull(bstrFormat);
+ CheckComArgOutPointerValid(ppProgress);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#if defined(VBOX_WITH_DRAG_AND_DROP) && defined(VBOX_WITH_DRAG_AND_DROP_GH)
+ return m_pGuestDnD->dragGHDropped(bstrFormat, action, ppProgress);
+#else /* VBOX_WITH_DRAG_AND_DROP */
+ ReturnComNotImplemented();
+#endif /* !VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP Guest::DragGHGetData(ComSafeArrayOut(BYTE, data))
+{
+ /* Input validation */
+ CheckComArgSafeArrayNotNull(data);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+#if defined(VBOX_WITH_DRAG_AND_DROP) && defined(VBOX_WITH_DRAG_AND_DROP_GH)
+ return m_pGuestDnD->dragGHGetData(ComSafeArrayOutArg(data));
+#else /* VBOX_WITH_DRAG_AND_DROP */
+ ReturnComNotImplemented();
+#endif /* !VBOX_WITH_DRAG_AND_DROP */
+}
+
// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
@@ -760,7 +1023,7 @@ void Guest::setAdditionsInfo(Bstr aInterfaceVersion, VBOXOSTYPE aOsType)
* mSupportsGraphics here and disabling/enabling it later according to
* its real status when using new(er) Guest Additions.
*/
- mData.mOSTypeId = Global::OSTypeId (aOsType);
+ mData.mOSTypeId = Global::OSTypeId(aOsType);
}
/**
@@ -927,4 +1190,4 @@ void Guest::setSupportedFeatures(uint32_t aCaps)
aCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS ? VBoxGuestFacilityStatus_Active : VBoxGuestFacilityStatus_Inactive,
0 /*fFlags*/, &TimeSpecTS);
}
-/* vi: set tabstop=4 shiftwidth=4 expandtab: */
+
diff --git a/src/VBox/Main/src-client/GuestProcessImpl.cpp b/src/VBox/Main/src-client/GuestProcessImpl.cpp
new file mode 100644
index 000000000..feffba96f
--- /dev/null
+++ b/src/VBox/Main/src-client/GuestProcessImpl.cpp
@@ -0,0 +1,2136 @@
+
+/* $Id: GuestProcessImpl.cpp $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/**
+ * Locking rules:
+ * - When the main dispatcher (callbackDispatcher) is called it takes the
+ * WriteLock while dispatching to the various on* methods.
+ * - All other outer functions (accessible by Main) must not own a lock
+ * while waiting for a callback or for an event.
+ * - Only keep Read/WriteLocks as short as possible and only when necessary.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "GuestProcessImpl.h"
+#include "GuestSessionImpl.h"
+#include "GuestCtrlImplPrivate.h"
+#include "ConsoleImpl.h"
+
+#include "Global.h"
+#include "AutoCaller.h"
+#include "VMMDev.h"
+
+#include <memory> /* For auto_ptr. */
+
+#include <iprt/asm.h>
+#include <iprt/getopt.h>
+#include <VBox/VMMDev.h>
+#include <VBox/com/array.h>
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
+#include <VBox/log.h>
+
+
+class GuestProcessTask
+{
+public:
+
+ GuestProcessTask(GuestProcess *pProcess)
+ : mProcess(pProcess),
+ mRC(VINF_SUCCESS) { }
+
+ virtual ~GuestProcessTask(void) { }
+
+ int rc(void) const { return mRC; }
+ bool isOk(void) const { return RT_SUCCESS(mRC); }
+ const ComObjPtr<GuestProcess> &Process(void) const { return mProcess; }
+
+protected:
+
+ const ComObjPtr<GuestProcess> mProcess;
+ int mRC;
+};
+
+class GuestProcessStartTask : public GuestProcessTask
+{
+public:
+
+ GuestProcessStartTask(GuestProcess *pProcess)
+ : GuestProcessTask(pProcess) { }
+};
+
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR(GuestProcess)
+
+HRESULT GuestProcess::FinalConstruct(void)
+{
+ LogFlowThisFuncEnter();
+
+ mData.mExitCode = 0;
+ mData.mNextContextID = 0;
+ mData.mPID = 0;
+ mData.mProcessID = 0;
+ mData.mRC = VINF_SUCCESS;
+ mData.mStatus = ProcessStatus_Undefined;
+
+ mData.mWaitCount = 0;
+ mData.mWaitEvent = NULL;
+
+ HRESULT hr = BaseFinalConstruct();
+ return hr;
+}
+
+void GuestProcess::FinalRelease(void)
+{
+ LogFlowThisFuncEnter();
+ uninit();
+ BaseFinalRelease();
+ LogFlowThisFuncLeave();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+int GuestProcess::init(Console *aConsole, GuestSession *aSession, ULONG aProcessID, const GuestProcessStartupInfo &aProcInfo)
+{
+ LogFlowThisFunc(("aConsole=%p, aSession=%p, aProcessID=%RU32\n",
+ aConsole, aSession, aProcessID));
+
+ AssertPtrReturn(aSession, VERR_INVALID_POINTER);
+
+ /* Enclose the state transition NotReady->InInit->Ready. */
+ AutoInitSpan autoInitSpan(this);
+ AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
+
+ mData.mConsole = aConsole;
+ mData.mParent = aSession;
+ mData.mProcessID = aProcessID;
+ mData.mProcess = aProcInfo;
+ /* Everything else will be set by the actual starting routine. */
+
+ /* Confirm a successful initialization when it's the case. */
+ autoInitSpan.setSucceeded();
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called from FinalRelease().
+ */
+void GuestProcess::uninit(void)
+{
+ LogFlowThisFunc(("mCmd=%s, PID=%RU32\n",
+ mData.mProcess.mCommand.c_str(), mData.mPID));
+
+ /* Enclose the state transition Ready->InUninit->NotReady. */
+ AutoUninitSpan autoUninitSpan(this);
+ if (autoUninitSpan.uninitDone())
+ return;
+
+ int vrc = VINF_SUCCESS;
+
+#ifdef VBOX_WITH_GUEST_CONTROL
+ /*
+ * Cancel all callbacks + waiters.
+ * Note: Deleting them is the job of the caller!
+ */
+ for (GuestCtrlCallbacks::iterator itCallbacks = mData.mCallbacks.begin();
+ itCallbacks != mData.mCallbacks.end(); ++itCallbacks)
+ {
+ GuestCtrlCallback *pCallback = itCallbacks->second;
+ AssertPtr(pCallback);
+ int rc2 = pCallback->Cancel();
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+ }
+ mData.mCallbacks.clear();
+
+ if (mData.mWaitEvent)
+ {
+ int rc2 = mData.mWaitEvent->Cancel();
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+ }
+
+ mData.mStatus = ProcessStatus_Down; /** @todo Correct? */
+#endif
+
+ LogFlowFuncLeaveRC(vrc);
+}
+
+// implementation of public getters/setters for attributes
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestProcess::COMGETTER(Arguments)(ComSafeArrayOut(BSTR, aArguments))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutSafeArrayPointerValid(aArguments);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ com::SafeArray<BSTR> collection(mData.mProcess.mArguments.size());
+ size_t s = 0;
+ for (ProcessArguments::const_iterator it = mData.mProcess.mArguments.begin();
+ it != mData.mProcess.mArguments.end();
+ it++, s++)
+ {
+ Bstr tmp = *it;
+ tmp.cloneTo(&collection[s]);
+ }
+
+ collection.detachTo(ComSafeArrayOutArg(aArguments));
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::COMGETTER(Environment)(ComSafeArrayOut(BSTR, aEnvironment))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutSafeArrayPointerValid(aEnvironment);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ com::SafeArray<BSTR> arguments(mData.mProcess.mEnvironment.Size());
+ for (size_t i = 0; i < arguments.size(); i++)
+ {
+ Bstr tmp = mData.mProcess.mEnvironment.Get(i);
+ tmp.cloneTo(&arguments[i]);
+ }
+ arguments.detachTo(ComSafeArrayOutArg(aEnvironment));
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::COMGETTER(ExecutablePath)(BSTR *aExecutablePath)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aExecutablePath);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mProcess.mCommand.cloneTo(aExecutablePath);
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::COMGETTER(ExitCode)(LONG *aExitCode)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aExitCode);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aExitCode = mData.mExitCode;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::COMGETTER(Name)(BSTR *aName)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aName);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mProcess.mName.cloneTo(aName);
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::COMGETTER(PID)(ULONG *aPID)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aPID);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aPID = mData.mPID;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::COMGETTER(Status)(ProcessStatus_T *aStatus)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aStatus = mData.mStatus;
+
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+// private methods
+/////////////////////////////////////////////////////////////////////////////
+
+inline int GuestProcess::callbackAdd(GuestCtrlCallback *pCallback, uint32_t *puContextID)
+{
+ const ComObjPtr<GuestSession> pSession(mData.mParent);
+ Assert(!pSession.isNull());
+ ULONG uSessionID = 0;
+ HRESULT hr = pSession->COMGETTER(Id)(&uSessionID);
+ ComAssertComRC(hr);
+
+ /* Create a new context ID and assign it. */
+ int vrc = VERR_NOT_FOUND;
+
+ ULONG uCount = mData.mNextContextID++;
+ ULONG uNewContextID = 0;
+ ULONG uTries = 0;
+ for (;;)
+ {
+ if (uCount == VBOX_GUESTCTRL_MAX_CONTEXTS)
+ uCount = 0;
+
+ /* Create a new context ID ... */
+ uNewContextID = VBOX_GUESTCTRL_CONTEXTID_MAKE(uSessionID,
+ mData.mProcessID, uCount);
+
+ /* Is the context ID already used? Try next ID ... */
+ if (!callbackExists(uCount))
+ {
+ /* Callback with context ID was not found. This means
+ * we can use this context ID for our new callback we want
+ * to add below. */
+ vrc = VINF_SUCCESS;
+ break;
+ }
+
+ uCount++;
+ if (++uTries == UINT32_MAX)
+ break; /* Don't try too hard. */
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ /* Add callback with new context ID to our callback map.
+ * Note: This is *not* uNewContextID (which also includes
+ * the session + process ID), just the context count
+ * will be used here. */
+ mData.mCallbacks[uCount] = pCallback;
+ Assert(mData.mCallbacks.size());
+
+ /* Report back new context ID. */
+ if (puContextID)
+ *puContextID = uNewContextID;
+
+ LogFlowThisFunc(("Added new callback (Session: %RU32, Process: %RU32, Count=%RU32) CID=%RU32\n",
+ uSessionID, mData.mProcessID, uCount, uNewContextID));
+ }
+
+ return vrc;
+}
+
+int GuestProcess::callbackDispatcher(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData)
+{
+#ifdef DEBUG
+ LogFlowThisFunc(("uPID=%RU32, uContextID=%RU32, uFunction=%RU32, pvData=%p, cbData=%RU32\n",
+ mData.mPID, uContextID, uFunction, pvData, cbData));
+#endif
+
+ AssertPtrReturn(pvData, VERR_INVALID_POINTER);
+ AssertReturn(cbData, VERR_INVALID_PARAMETER);
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ int vrc;
+
+ /* Get the optional callback associated to this context ID.
+ * The callback may not be around anymore if just kept locally by the caller when
+ * doing the actual HGCM sending stuff. */
+ GuestCtrlCallback *pCallback = NULL;
+ GuestCtrlCallbacks::const_iterator it
+ = mData.mCallbacks.find(VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID));
+ if (it != mData.mCallbacks.end())
+ {
+ pCallback = it->second;
+ AssertPtr(pCallback);
+#ifdef DEBUG
+ LogFlowThisFunc(("pCallback=%p, CID=%RU32, Count=%RU32\n",
+ pCallback, uContextID, VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID)));
+#endif
+ }
+
+ switch (uFunction)
+ {
+ case GUEST_DISCONNECTED:
+ {
+ PCALLBACKDATACLIENTDISCONNECTED pCallbackData = reinterpret_cast<PCALLBACKDATACLIENTDISCONNECTED>(pvData);
+ AssertPtr(pCallbackData);
+ AssertReturn(sizeof(CALLBACKDATACLIENTDISCONNECTED) == cbData, VERR_INVALID_PARAMETER);
+ AssertReturn(CALLBACKDATAMAGIC_CLIENT_DISCONNECTED == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+ vrc = onGuestDisconnected(pCallback, pCallbackData); /* Affects all callbacks. */
+ break;
+ }
+
+ case GUEST_EXEC_SEND_STATUS:
+ {
+ PCALLBACKDATAEXECSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvData);
+ AssertPtr(pCallbackData);
+ AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbData, VERR_INVALID_PARAMETER);
+ AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+ vrc = onProcessStatusChange(pCallback, pCallbackData);
+ break;
+ }
+
+ case GUEST_EXEC_SEND_OUTPUT:
+ {
+ PCALLBACKDATAEXECOUT pCallbackData = reinterpret_cast<PCALLBACKDATAEXECOUT>(pvData);
+ AssertPtr(pCallbackData);
+ AssertReturn(sizeof(CALLBACKDATAEXECOUT) == cbData, VERR_INVALID_PARAMETER);
+ AssertReturn(CALLBACKDATAMAGIC_EXEC_OUT == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+ vrc = onProcessOutput(pCallback, pCallbackData);
+ break;
+ }
+
+ case GUEST_EXEC_SEND_INPUT_STATUS:
+ {
+ PCALLBACKDATAEXECINSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECINSTATUS>(pvData);
+ AssertPtr(pCallbackData);
+ AssertReturn(sizeof(CALLBACKDATAEXECINSTATUS) == cbData, VERR_INVALID_PARAMETER);
+ AssertReturn(CALLBACKDATAMAGIC_EXEC_IN_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+ vrc = onProcessInputStatus(pCallback, pCallbackData);
+ break;
+ }
+
+ default:
+ /* Silently ignore not implemented functions. */
+ vrc = VERR_NOT_IMPLEMENTED;
+ break;
+ }
+
+#ifdef DEBUG
+ LogFlowFuncLeaveRC(vrc);
+#endif
+ return vrc;
+}
+
+inline bool GuestProcess::callbackExists(uint32_t uContextID)
+{
+ GuestCtrlCallbacks::const_iterator it =
+ mData.mCallbacks.find(VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID));
+ return (it == mData.mCallbacks.end()) ? false : true;
+}
+
+inline int GuestProcess::callbackRemove(uint32_t uContextID)
+{
+ LogFlowThisFunc(("Removing callback (Session: %RU32, Process: %RU32, Count=%RU32) CID=%RU32\n",
+ VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID),
+ VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(uContextID),
+ VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID),
+ uContextID));
+
+ GuestCtrlCallbacks::iterator it =
+ mData.mCallbacks.find(VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID));
+ if (it != mData.mCallbacks.end())
+ {
+ delete it->second;
+ mData.mCallbacks.erase(it);
+
+ return VINF_SUCCESS;
+ }
+
+ return VERR_NOT_FOUND;
+}
+
+/**
+ * Checks if the current assigned PID matches another PID (from a callback).
+ *
+ * In protocol v1 we don't have the possibility to terminate/kill
+ * processes so it can happen that a formerly start process A
+ * (which has the context ID 0 (session=0, process=0, count=0) will
+ * send a delayed message to the host if this process has already
+ * been discarded there and the same context ID was reused by
+ * a process B. Process B in turn then has a different guest PID.
+ *
+ * @return IPRT status code.
+ * @param uPID PID to check.
+ */
+inline int GuestProcess::checkPID(uint32_t uPID)
+{
+ /* Was there a PID assigned yet? */
+ if (mData.mPID)
+ {
+ /*
+
+ */
+ if (mData.mParent->getProtocolVersion() < 2)
+ {
+ /* Simply ignore the stale requests. */
+ return (mData.mPID == uPID)
+ ? VINF_SUCCESS : VERR_NOT_FOUND;
+ }
+ /* This should never happen! */
+ AssertReleaseMsg(mData.mPID == uPID, ("Unterminated guest process (PID %RU32) sent data to a newly started process (PID %RU32)\n",
+ uPID, mData.mPID));
+ }
+
+ return VINF_SUCCESS;
+}
+
+/* static */
+Utf8Str GuestProcess::guestErrorToString(int guestRc)
+{
+ Utf8Str strError;
+
+ /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
+ switch (guestRc)
+ {
+ case VERR_FILE_NOT_FOUND: /* This is the most likely error. */
+ strError += Utf8StrFmt(tr("The specified file was not found on guest"));
+ break;
+
+ case VERR_INVALID_VM_HANDLE:
+ strError += Utf8StrFmt(tr("VMM device is not available (is the VM running?)"));
+ break;
+
+ case VERR_HGCM_SERVICE_NOT_FOUND:
+ strError += Utf8StrFmt(tr("The guest execution service is not available"));
+ break;
+
+ case VERR_PATH_NOT_FOUND:
+ strError += Utf8StrFmt(tr("Could not resolve path to specified file was not found on guest"));
+ break;
+
+ case VERR_BAD_EXE_FORMAT:
+ strError += Utf8StrFmt(tr("The specified file is not an executable format on guest"));
+ break;
+
+ case VERR_AUTHENTICATION_FAILURE:
+ strError += Utf8StrFmt(tr("The specified user was not able to logon on guest"));
+ break;
+
+ case VERR_INVALID_NAME:
+ strError += Utf8StrFmt(tr("The specified file is an invalid name"));
+ break;
+
+ case VERR_TIMEOUT:
+ strError += Utf8StrFmt(tr("The guest did not respond within time"));
+ break;
+
+ case VERR_CANCELLED:
+ strError += Utf8StrFmt(tr("The execution operation was canceled"));
+ break;
+
+ case VERR_PERMISSION_DENIED:
+ strError += Utf8StrFmt(tr("Invalid user/password credentials"));
+ break;
+
+ case VERR_MAX_PROCS_REACHED:
+ strError += Utf8StrFmt(tr("Maximum number of parallel guest processes has been reached"));
+ break;
+
+ case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
+ strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
+ break;
+
+ case VERR_NOT_FOUND:
+ strError += Utf8StrFmt(tr("The guest execution service is not ready (yet)"));
+ break;
+
+ default:
+ strError += Utf8StrFmt(tr("%Rrc"), guestRc);
+ break;
+ }
+
+ return strError;
+}
+
+inline bool GuestProcess::isAlive(void)
+{
+ return ( mData.mStatus == ProcessStatus_Started
+ || mData.mStatus == ProcessStatus_Paused
+ || mData.mStatus == ProcessStatus_Terminating);
+}
+
+bool GuestProcess::isReady(void)
+{
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (mData.mStatus == ProcessStatus_Started)
+ {
+ Assert(mData.mPID); /* PID must not be 0. */
+ return true;
+ }
+
+ return false;
+}
+
+int GuestProcess::onGuestDisconnected(GuestCtrlCallback *pCallback, PCALLBACKDATACLIENTDISCONNECTED pData)
+{
+ /* pCallback is optional. */
+ AssertPtrReturn(pData, VERR_INVALID_POINTER);
+
+ LogFlowThisFunc(("uPID=%RU32, pCallback=%p, pData=%p\n", mData.mPID, pCallback, pData));
+
+ mData.mStatus = ProcessStatus_Down;
+
+ /* First, signal callback in every case. */
+ if (pCallback)
+ pCallback->Signal();
+
+ /* Do we need to report a termination? */
+ ProcessWaitResult_T waitRes;
+ if (mData.mProcess.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
+ waitRes = ProcessWaitResult_Status; /* No, just report a status. */
+ else
+ waitRes = ProcessWaitResult_Terminate;
+
+ /* Signal in any case. */
+ int vrc = signalWaiters(waitRes);
+ AssertRC(vrc);
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::onProcessInputStatus(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECINSTATUS pData)
+{
+ /* pCallback is optional. */
+ AssertPtrReturn(pData, VERR_INVALID_POINTER);
+
+ LogFlowThisFunc(("uPID=%RU32, uStatus=%RU32, uFlags=%RU32, cbProcessed=%RU32, pCallback=%p, pData=%p\n",
+ mData.mPID, pData->u32Status, pData->u32Flags, pData->cbProcessed, pCallback, pData));
+
+ int vrc = checkPID(pData->u32PID);
+ if (RT_FAILURE(vrc))
+ return vrc;
+
+ /* First, signal callback in every case (if available). */
+ if (pCallback)
+ {
+ vrc = pCallback->SetData(pData, sizeof(CALLBACKDATAEXECINSTATUS));
+
+ int rc2 = pCallback->Signal();
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+ }
+
+ /* Then do the WaitFor signalling stuff. */
+ uint32_t uWaitFlags = mData.mWaitEvent
+ ? mData.mWaitEvent->GetWaitFlags() : 0;
+ if (uWaitFlags & ProcessWaitForFlag_StdIn)
+ {
+ int rc2 = signalWaiters(ProcessWaitResult_StdIn);
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::onProcessNotifyIO(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData)
+{
+ /* pCallback is optional. */
+ AssertPtrReturn(pData, VERR_INVALID_POINTER);
+
+ return 0;
+}
+
+int GuestProcess::onProcessStatusChange(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECSTATUS pData)
+{
+ /* pCallback is optional. */
+ AssertPtrReturn(pData, VERR_INVALID_POINTER);
+
+ LogFlowThisFunc(("uPID=%RU32, uStatus=%RU32, uFlags=%RU32, pCallback=%p, pData=%p\n",
+ pData->u32PID, pData->u32Status, pData->u32Flags, pCallback, pData));
+
+ int vrc = checkPID(pData->u32PID);
+ if (RT_FAILURE(vrc))
+ return vrc;
+
+ ProcessStatus_T procStatus = ProcessStatus_Undefined;
+ int procRc = VINF_SUCCESS;
+
+ bool fSignalWaiters = false;
+ ProcessWaitResult_T waitRes;
+
+ uint32_t uWaitFlags = mData.mWaitEvent
+ ? mData.mWaitEvent->GetWaitFlags() : 0;
+ switch (pData->u32Status)
+ {
+ case PROC_STS_STARTED:
+ {
+ fSignalWaiters = (uWaitFlags & ProcessWaitForFlag_Start);
+ /* If the caller only wants to wait until the process has been started,
+ * notify in any case. */
+ if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
+ fSignalWaiters = true;
+ waitRes = ProcessWaitResult_Start;
+
+ procStatus = ProcessStatus_Started;
+ mData.mPID = pData->u32PID; /* Set the process PID. */
+ break;
+ }
+
+ case PROC_STS_TEN:
+ {
+ fSignalWaiters = true; /* Signal in any case. */
+ waitRes = ProcessWaitResult_Terminate;
+
+ procStatus = ProcessStatus_TerminatedNormally;
+ mData.mExitCode = pData->u32Flags; /* Contains the exit code. */
+ break;
+ }
+
+ case PROC_STS_TES:
+ {
+ fSignalWaiters = true; /* Signal in any case. */
+ waitRes = ProcessWaitResult_Terminate;
+
+ procStatus = ProcessStatus_TerminatedSignal;
+ mData.mExitCode = pData->u32Flags; /* Contains the signal. */
+ break;
+ }
+
+ case PROC_STS_TEA:
+ {
+ fSignalWaiters = true; /* Signal in any case. */
+ waitRes = ProcessWaitResult_Terminate;
+
+ procStatus = ProcessStatus_TerminatedAbnormally;
+ break;
+ }
+
+ case PROC_STS_TOK:
+ {
+ fSignalWaiters = true; /* Signal in any case. */
+ waitRes = ProcessWaitResult_Timeout;
+
+ procStatus = ProcessStatus_TimedOutKilled;
+ break;
+ }
+
+ case PROC_STS_TOA:
+ {
+ fSignalWaiters = true; /* Signal in any case. */
+ waitRes = ProcessWaitResult_Timeout;
+
+ procStatus = ProcessStatus_TimedOutAbnormally;
+ break;
+ }
+
+ case PROC_STS_DWN:
+ {
+ fSignalWaiters = true; /* Signal in any case. */
+ /* Do we need to report termination? */
+ if (mData.mProcess.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
+ waitRes = ProcessWaitResult_Status;
+ else
+ waitRes = ProcessWaitResult_Terminate;
+
+ procStatus = ProcessStatus_Down;
+ break;
+ }
+
+ case PROC_STS_ERROR:
+ {
+ fSignalWaiters = true; /* Signal in any case. */
+ waitRes = ProcessWaitResult_Error;
+
+ procRc = pData->u32Flags; /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
+ procStatus = ProcessStatus_Error;
+ break;
+ }
+
+ case PROC_STS_UNDEFINED:
+ default:
+ {
+ /* Silently skip this request. */
+ fSignalWaiters = true; /* Signal in any case. */
+ waitRes = ProcessWaitResult_Status;
+
+ procStatus = ProcessStatus_Undefined;
+ break;
+ }
+ }
+
+ LogFlowThisFunc(("Got rc=%Rrc, waitRes=%d, procSts=%ld, procRc=%Rrc, fSignalWaiters=%RTbool\n",
+ vrc, waitRes, procStatus, procRc, fSignalWaiters));
+
+ /* Set the process status. */
+ int rc2 = setProcessStatus(procStatus, procRc);
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+
+ /*
+ * Now do the signalling stuff.
+ */
+ if (pCallback)
+ vrc = pCallback->Signal(procRc);
+
+ if (fSignalWaiters)
+ {
+ rc2 = signalWaiters(waitRes, procRc);
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::onProcessOutput(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECOUT pData)
+{
+ /* pCallback is optional. */
+ AssertPtrReturn(pData, VERR_INVALID_POINTER);
+
+ LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uFlags=%RU32, pvData=%p, cbData=%RU32, pCallback=%p, pData=%p\n",
+ mData.mPID, pData->u32HandleId, pData->u32Flags, pData->pvData, pData->cbData, pCallback, pData));
+
+ int vrc = checkPID(pData->u32PID);
+ if (RT_FAILURE(vrc))
+ return vrc;
+
+ /* First, signal callback in every case (if available). */
+ if (pCallback)
+ {
+ vrc = pCallback->SetData(pData, sizeof(CALLBACKDATAEXECOUT));
+
+ int rc2 = pCallback->Signal();
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+ }
+
+ /* Then do the WaitFor signalling stuff. */
+ BOOL fSignal = FALSE;
+ uint32_t uWaitFlags = mData.mWaitEvent
+ ? mData.mWaitEvent->GetWaitFlags() : 0;
+
+ if ( (uWaitFlags & ProcessWaitForFlag_StdOut)
+ || (uWaitFlags & ProcessWaitForFlag_StdErr))
+ {
+ fSignal = TRUE;
+ }
+ else if ( (uWaitFlags & ProcessWaitForFlag_StdOut)
+ && (pData->u32HandleId == OUTPUT_HANDLE_ID_STDOUT))
+ {
+ fSignal = TRUE;
+ }
+ else if ( (uWaitFlags & ProcessWaitForFlag_StdErr)
+ && (pData->u32HandleId == OUTPUT_HANDLE_ID_STDERR))
+ {
+ fSignal = TRUE;
+ }
+
+ if (fSignal)
+ {
+ int rc2;
+ if (pData->u32HandleId == OUTPUT_HANDLE_ID_STDOUT)
+ rc2 = signalWaiters(ProcessWaitResult_StdOut);
+ else
+ rc2 = signalWaiters(ProcessWaitResult_StdErr);
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS,
+ void *pvData, size_t cbData, size_t *pcbRead, int *pGuestRc)
+{
+ LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%RU32, pGuestRc=%p\n",
+ mData.mPID, uHandle, uSize, uTimeoutMS, pvData, cbData, pGuestRc));
+ AssertReturn(uSize, VERR_INVALID_PARAMETER);
+ AssertPtrReturn(pvData, VERR_INVALID_POINTER);
+ AssertReturn(cbData >= uSize, VERR_INVALID_PARAMETER);
+ /* pcbRead is optional. */
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (mData.mStatus != ProcessStatus_Started)
+ {
+ if (pcbRead)
+ *pcbRead = 0;
+ if (pGuestRc)
+ *pGuestRc = VINF_SUCCESS;
+ return VINF_SUCCESS; /* Nothing to read anymore. */
+ }
+
+ int vrc = VINF_SUCCESS;
+
+ GuestCtrlCallback *pCallbackRead = NULL;
+ try
+ {
+ pCallbackRead = new GuestCtrlCallback();
+ }
+ catch(std::bad_alloc &)
+ {
+ vrc = VERR_NO_MEMORY;
+ }
+
+ /* Create callback and add it to the map. */
+ uint32_t uContextID = 0;
+ if (RT_SUCCESS(vrc))
+ {
+ vrc = pCallbackRead->Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT);
+ if (RT_SUCCESS(vrc))
+ vrc = callbackAdd(pCallbackRead, &uContextID);
+ }
+
+ alock.release(); /* Drop the write lock again. */
+
+ if (RT_SUCCESS(vrc))
+ {
+ VBOXHGCMSVCPARM paParms[5];
+
+ int i = 0;
+ paParms[i++].setUInt32(uContextID);
+ paParms[i++].setUInt32(mData.mPID);
+ paParms[i++].setUInt32(uHandle);
+ paParms[i++].setUInt32(0 /* Flags, none set yet. */);
+
+ vrc = sendCommand(HOST_EXEC_GET_OUTPUT, i, paParms);
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ /*
+ * Let's wait for the process being started.
+ * Note: Be sure not keeping a AutoRead/WriteLock here.
+ */
+ LogFlowThisFunc(("Waiting for callback (%RU32ms) ...\n", uTimeoutMS));
+ vrc = pCallbackRead->Wait(uTimeoutMS);
+ if (RT_SUCCESS(vrc)) /* Wait was successful, check for supplied information. */
+ {
+ int guestRc = pCallbackRead->GetResultCode();
+ LogFlowThisFunc(("Callback returned rc=%Rrc, cbData=%RU32\n", guestRc, pCallbackRead->GetDataSize()));
+
+ if (RT_SUCCESS(guestRc))
+ {
+ Assert(pCallbackRead->GetDataSize() == sizeof(CALLBACKDATAEXECOUT));
+ PCALLBACKDATAEXECOUT pData = (PCALLBACKDATAEXECOUT)pCallbackRead->GetDataRaw();
+ AssertPtr(pData);
+
+ size_t cbRead = pData->cbData;
+ if (cbRead)
+ {
+ Assert(cbData >= cbRead);
+ memcpy(pvData, pData->pvData, cbRead);
+ }
+
+ LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
+
+ if (pcbRead)
+ *pcbRead = cbRead;
+ }
+ else
+ vrc = VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+
+ if (pGuestRc)
+ *pGuestRc = guestRc;
+ }
+ }
+
+ alock.acquire();
+
+ AssertPtr(pCallbackRead);
+ int rc2 = callbackRemove(uContextID);
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::sendCommand(uint32_t uFunction,
+ uint32_t uParms, PVBOXHGCMSVCPARM paParms)
+{
+ LogFlowThisFuncEnter();
+
+ ComObjPtr<Console> pConsole = mData.mConsole;
+ Assert(!pConsole.isNull());
+
+ /* Forward the information to the VMM device. */
+ VMMDev *pVMMDev = pConsole->getVMMDev();
+ AssertPtr(pVMMDev);
+
+ LogFlowThisFunc(("uFunction=%RU32, uParms=%RU32\n", uFunction, uParms));
+ int vrc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", uFunction, uParms, paParms);
+ if (RT_FAILURE(vrc))
+ {
+ int rc2 = setProcessStatus(ProcessStatus_Error, vrc);
+ AssertRC(rc2);
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+/* Does not do locking; caller is responsible for that! */
+int GuestProcess::setProcessStatus(ProcessStatus_T procStatus, int procRc)
+{
+ LogFlowThisFunc(("oldStatus=%ld, newStatus=%ld, procRc=%Rrc\n",
+ mData.mStatus, procStatus, procRc));
+
+#ifdef DEBUG
+ if (procStatus == ProcessStatus_Error)
+ {
+ AssertMsg(RT_FAILURE(procRc), ("Guest rc must be an error (%Rrc)\n", procRc));
+ /* Do not allow overwriting an already set error. If this happens
+ * this means we forgot some error checking/locking somewhere. */
+ AssertMsg(RT_SUCCESS(mData.mRC), ("Guest rc already set (to %Rrc)\n", mData.mRC));
+ }
+ else
+ AssertMsg(RT_SUCCESS(procRc), ("Guest rc must not be an error (%Rrc)\n", procRc));
+#endif
+
+ mData.mStatus = procStatus;
+ mData.mRC = procRc;
+
+ return VINF_SUCCESS;
+}
+
+/* static */
+HRESULT GuestProcess::setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
+{
+ AssertPtr(pInterface);
+ AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
+
+ return pInterface->setError(VBOX_E_IPRT_ERROR, GuestProcess::guestErrorToString(guestRc).c_str());
+}
+
+int GuestProcess::signalWaiters(ProcessWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS */)
+{
+ LogFlowThisFunc(("enmWaitResult=%d, rc=%Rrc, mWaitCount=%RU32, mWaitEvent=%p\n",
+ enmWaitResult, rc, mData.mWaitCount, mData.mWaitEvent));
+
+ /* Note: No write locking here -- already done in the caller. */
+
+ int vrc = VINF_SUCCESS;
+ if (mData.mWaitEvent)
+ vrc = mData.mWaitEvent->Signal(enmWaitResult, rc);
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::startProcess(int *pGuestRc)
+{
+ LogFlowThisFunc(("aCmd=%s, aTimeoutMS=%RU32, fFlags=%x\n",
+ mData.mProcess.mCommand.c_str(), mData.mProcess.mTimeoutMS, mData.mProcess.mFlags));
+
+ /* Wait until the caller function (if kicked off by a thread)
+ * has returned and continue operation. */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ int vrc = VINF_SUCCESS;
+ uint32_t uContextID = 0;
+
+ GuestCtrlCallback *pCallbackStart;
+ try
+ {
+ pCallbackStart = new GuestCtrlCallback();
+ }
+ catch(std::bad_alloc &)
+ {
+ vrc = VERR_NO_MEMORY;
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ mData.mStatus = ProcessStatus_Starting;
+
+ /* Create callback and add it to the map. */
+ vrc = pCallbackStart->Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START);
+ if (RT_SUCCESS(vrc))
+ vrc = callbackAdd(pCallbackStart, &uContextID);
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ GuestSession *pSession = mData.mParent;
+ AssertPtr(pSession);
+
+ const GuestCredentials &sessionCreds = pSession->getCredentials();
+
+ /* Prepare arguments. */
+ char *pszArgs = NULL;
+ size_t cArgs = mData.mProcess.mArguments.size();
+ if (cArgs >= UINT32_MAX)
+ vrc = VERR_BUFFER_OVERFLOW;
+
+ if ( RT_SUCCESS(vrc)
+ && cArgs)
+ {
+ char **papszArgv = (char**)RTMemAlloc((cArgs + 1) * sizeof(char*));
+ AssertReturn(papszArgv, VERR_NO_MEMORY);
+
+ for (size_t i = 0; i < cArgs && RT_SUCCESS(vrc); i++)
+ {
+ const char *pszCurArg = mData.mProcess.mArguments[i].c_str();
+ AssertPtr(pszCurArg);
+ vrc = RTStrDupEx(&papszArgv[i], pszCurArg);
+ }
+ papszArgv[cArgs] = NULL;
+
+ if (RT_SUCCESS(vrc))
+ vrc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT);
+
+ if (papszArgv)
+ {
+ size_t i = 0;
+ while (papszArgv[i])
+ RTStrFree(papszArgv[i++]);
+ RTMemFree(papszArgv);
+ }
+ }
+
+ /* Calculate arguments size (in bytes). */
+ size_t cbArgs = 0;
+ if (RT_SUCCESS(vrc))
+ cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
+
+ /* Prepare environment. */
+ void *pvEnv = NULL;
+ size_t cbEnv = 0;
+ if (RT_SUCCESS(vrc))
+ vrc = mData.mProcess.mEnvironment.BuildEnvironmentBlock(&pvEnv, &cbEnv, NULL /* cEnv */);
+
+ if (RT_SUCCESS(vrc))
+ {
+ /* Prepare HGCM call. */
+ VBOXHGCMSVCPARM paParms[15];
+ int i = 0;
+ paParms[i++].setUInt32(uContextID);
+ paParms[i++].setPointer((void*)mData.mProcess.mCommand.c_str(),
+ (ULONG)mData.mProcess.mCommand.length() + 1);
+ paParms[i++].setUInt32(mData.mProcess.mFlags);
+ paParms[i++].setUInt32(mData.mProcess.mArguments.size());
+ paParms[i++].setPointer((void*)pszArgs, cbArgs);
+ paParms[i++].setUInt32(mData.mProcess.mEnvironment.Size());
+ paParms[i++].setUInt32(cbEnv);
+ paParms[i++].setPointer((void*)pvEnv, cbEnv);
+ paParms[i++].setPointer((void*)sessionCreds.mUser.c_str(), (ULONG)sessionCreds.mUser.length() + 1);
+ paParms[i++].setPointer((void*)sessionCreds.mPassword.c_str(), (ULONG)sessionCreds.mPassword.length() + 1);
+ /** @todo New command needs the domain as well! */
+
+ /*
+ * If the WaitForProcessStartOnly flag is set, we only want to define and wait for a timeout
+ * until the process was started - the process itself then gets an infinite timeout for execution.
+ * This is handy when we want to start a process inside a worker thread within a certain timeout
+ * but let the started process perform lengthly operations then.
+ */
+ if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
+ paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */);
+ else
+ paParms[i++].setUInt32(mData.mProcess.mTimeoutMS);
+
+ /* Note: Don't hold the write lock in here, because setErrorInternal */
+ vrc = sendCommand(HOST_EXEC_CMD, i, paParms);
+ }
+
+ GuestEnvironment::FreeEnvironmentBlock(pvEnv);
+ if (pszArgs)
+ RTStrFree(pszArgs);
+
+ uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS;
+
+ /* Drop the write lock again before waiting. */
+ alock.release();
+
+ if (RT_SUCCESS(vrc))
+ {
+ /*
+ * Let's wait for the process being started.
+ * Note: Be sure not keeping a AutoRead/WriteLock here.
+ */
+ LogFlowThisFunc(("Waiting for callback (%RU32ms) ...\n", uTimeoutMS));
+ vrc = pCallbackStart->Wait(uTimeoutMS);
+ if (RT_SUCCESS(vrc)) /* Wait was successful, check for supplied information. */
+ {
+ int guestRc = pCallbackStart->GetResultCode();
+ if (pGuestRc)
+ *pGuestRc = guestRc;
+ LogFlowThisFunc(("Callback returned rc=%Rrc\n", guestRc));
+ }
+ else
+ vrc = VERR_TIMEOUT;
+ }
+
+ AutoWriteLock awlock(this COMMA_LOCKVAL_SRC_POS);
+
+ AssertPtr(pCallbackStart);
+ int rc2 = callbackRemove(uContextID);
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::startProcessAsync(void)
+{
+ LogFlowThisFuncEnter();
+
+ int vrc;
+
+ try
+ {
+ /* Asynchronously start the process on the guest by kicking off a
+ * worker thread. */
+ std::auto_ptr<GuestProcessStartTask> pTask(new GuestProcessStartTask(this));
+ AssertReturn(pTask->isOk(), pTask->rc());
+
+ vrc = RTThreadCreate(NULL, GuestProcess::startProcessThread,
+ (void *)pTask.get(), 0,
+ RTTHREADTYPE_MAIN_WORKER, 0,
+ "gctlPrcStart");
+ if (RT_SUCCESS(vrc))
+ {
+ /* pTask is now owned by startProcessThread(), so release it. */
+ pTask.release();
+ }
+ }
+ catch(std::bad_alloc &)
+ {
+ vrc = VERR_NO_MEMORY;
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+/* static */
+DECLCALLBACK(int) GuestProcess::startProcessThread(RTTHREAD Thread, void *pvUser)
+{
+ LogFlowFunc(("pvUser=%p\n", pvUser));
+
+ std::auto_ptr<GuestProcessStartTask> pTask(static_cast<GuestProcessStartTask*>(pvUser));
+ AssertPtr(pTask.get());
+
+ const ComObjPtr<GuestProcess> pProcess(pTask->Process());
+ Assert(!pProcess.isNull());
+
+ AutoCaller autoCaller(pProcess);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ int vrc = pProcess->startProcess(NULL /* Guest rc, ignored */);
+ /* Nothing to do here anymore. */
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::terminateProcess(void)
+{
+ LogFlowThisFuncEnter();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (mData.mParent->getProtocolVersion() < 2)
+ return VERR_NOT_SUPPORTED;
+
+ LogFlowThisFuncLeave();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc)
+{
+ LogFlowThisFuncEnter();
+
+ AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER);
+
+ LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, mStatus=%RU32, mWaitCount=%RU32, mWaitEvent=%p, pGuestRc=%p\n",
+ fWaitFlags, uTimeoutMS, mData.mStatus, mData.mWaitCount, mData.mWaitEvent, pGuestRc));
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ /* Did some error occur before? Then skip waiting and return. */
+ if (mData.mStatus == ProcessStatus_Error)
+ {
+ waitResult = ProcessWaitResult_Error;
+ AssertMsg(RT_FAILURE(mData.mRC), ("No error rc (%Rrc) set when guest process indicated an error\n", mData.mRC));
+ if (pGuestRc)
+ *pGuestRc = mData.mRC; /* Return last set error. */
+ return VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+ }
+
+ waitResult = ProcessWaitResult_None;
+ if ( (fWaitFlags & ProcessWaitForFlag_Terminate)
+ || (fWaitFlags & ProcessWaitForFlag_StdIn)
+ || (fWaitFlags & ProcessWaitForFlag_StdOut)
+ || (fWaitFlags & ProcessWaitForFlag_StdErr))
+ {
+ switch (mData.mStatus)
+ {
+ case ProcessStatus_TerminatedNormally:
+ case ProcessStatus_TerminatedSignal:
+ case ProcessStatus_TerminatedAbnormally:
+ case ProcessStatus_Down:
+ waitResult = ProcessWaitResult_Terminate;
+ break;
+
+ case ProcessStatus_TimedOutKilled:
+ case ProcessStatus_TimedOutAbnormally:
+ waitResult = ProcessWaitResult_Timeout;
+ break;
+
+ case ProcessStatus_Error:
+ /* Handled above. */
+ break;
+
+ case ProcessStatus_Started:
+ {
+ /*
+ * If ProcessCreateFlag_WaitForProcessStartOnly was specified on process creation the
+ * caller is not interested in getting further process statuses -- so just don't notify
+ * anything here anymore and return.
+ */
+ if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
+ waitResult = ProcessWaitResult_Start;
+ break;
+ }
+
+ case ProcessStatus_Undefined:
+ case ProcessStatus_Starting:
+ /* Do the waiting below. */
+ break;
+
+ default:
+ AssertMsgFailed(("Unhandled process status %ld\n", mData.mStatus));
+ return VERR_NOT_IMPLEMENTED;
+ }
+ }
+ else if (fWaitFlags & ProcessWaitForFlag_Start)
+ {
+ switch (mData.mStatus)
+ {
+ case ProcessStatus_Started:
+ case ProcessStatus_Paused:
+ case ProcessStatus_Terminating:
+ case ProcessStatus_TerminatedNormally:
+ case ProcessStatus_TerminatedSignal:
+ case ProcessStatus_TerminatedAbnormally:
+ case ProcessStatus_Down:
+ waitResult = ProcessWaitResult_Start;
+ break;
+
+ case ProcessStatus_Error:
+ waitResult = ProcessWaitResult_Error;
+ break;
+
+ case ProcessStatus_TimedOutKilled:
+ case ProcessStatus_TimedOutAbnormally:
+ waitResult = ProcessWaitResult_Timeout;
+ break;
+
+ case ProcessStatus_Undefined:
+ case ProcessStatus_Starting:
+ /* Do the waiting below. */
+ break;
+
+ default:
+ AssertMsgFailed(("Unhandled process status %ld\n", mData.mStatus));
+ return VERR_NOT_IMPLEMENTED;
+ }
+ }
+
+ /* Filter out waits which are *not* supported using
+ * older guest control Guest Additions. */
+ if (mData.mParent->getProtocolVersion() < 2)
+ {
+ if ( waitResult == ProcessWaitResult_None
+ /* We don't support waiting for stdin, out + err,
+ * just skip waiting then. */
+ && ( (fWaitFlags & ProcessWaitForFlag_StdIn)
+ || (fWaitFlags & ProcessWaitForFlag_StdOut)
+ || (fWaitFlags & ProcessWaitForFlag_StdErr)
+ )
+ )
+ {
+ /* Use _WaitFlagNotSupported because we don't know what to tell the caller. */
+ waitResult = ProcessWaitResult_WaitFlagNotSupported;
+ }
+ }
+
+ LogFlowThisFunc(("procStatus=%ld, procRc=%Rrc, waitResult=%ld\n",
+ mData.mStatus, mData.mRC, waitResult));
+
+ /* No waiting needed? Return immediately using the last set error. */
+ if (waitResult != ProcessWaitResult_None)
+ {
+ if (pGuestRc)
+ *pGuestRc = mData.mRC; /* Return last set error (if any). */
+ return RT_SUCCESS(mData.mRC) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+ }
+
+ if (mData.mWaitCount > 0)
+ return VERR_ALREADY_EXISTS;
+ mData.mWaitCount++;
+
+ int vrc = VINF_SUCCESS;
+ try
+ {
+ Assert(mData.mWaitEvent == NULL);
+ mData.mWaitEvent = new GuestProcessWaitEvent(fWaitFlags);
+ }
+ catch(std::bad_alloc &)
+ {
+ vrc = VERR_NO_MEMORY;
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ GuestProcessWaitEvent *pEvent = mData.mWaitEvent;
+ AssertPtr(pEvent);
+
+ alock.release(); /* Release lock before waiting. */
+
+ vrc = pEvent->Wait(uTimeoutMS);
+ LogFlowThisFunc(("Waiting completed with rc=%Rrc\n", vrc));
+ if (RT_SUCCESS(vrc))
+ {
+ waitResult = pEvent->GetWaitResult();
+ int waitRc = pEvent->GetWaitRc();
+
+ LogFlowThisFunc(("Waiting event returned rc=%Rrc\n", waitRc));
+
+ if (pGuestRc)
+ *pGuestRc = waitRc;
+
+ vrc = RT_SUCCESS(waitRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+ }
+
+ alock.acquire(); /* Get the lock again. */
+
+ /* Note: The caller always is responsible of deleting the
+ * stuff it created before. See close() for more information. */
+ delete mData.mWaitEvent;
+ mData.mWaitEvent = NULL;
+ }
+
+ Assert(mData.mWaitCount);
+ mData.mWaitCount--;
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcess::writeData(uint32_t uHandle, uint32_t uFlags,
+ void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten, int *pGuestRc)
+{
+ LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uFlags=%RU32, pvData=%p, cbData=%RU32, uTimeoutMS=%RU32, puWritten=%p, pGuestRc=%p\n",
+ mData.mPID, uHandle, uFlags, pvData, cbData, uTimeoutMS, puWritten, pGuestRc));
+ /* All is optional. There can be 0 byte writes. */
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (mData.mStatus != ProcessStatus_Started)
+ {
+ if (puWritten)
+ *puWritten = 0;
+ if (pGuestRc)
+ *pGuestRc = VINF_SUCCESS;
+ return VINF_SUCCESS; /* Not available for writing (anymore). */
+ }
+
+ int vrc = VINF_SUCCESS;
+
+ GuestCtrlCallback *pCallbackWrite = NULL;
+ try
+ {
+ pCallbackWrite = new GuestCtrlCallback();
+ }
+ catch(std::bad_alloc &)
+ {
+ vrc = VERR_NO_MEMORY;
+ }
+
+ /* Create callback and add it to the map. */
+ uint32_t uContextID = 0;
+ if (RT_SUCCESS(vrc))
+ {
+ vrc = pCallbackWrite->Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS);
+ if (RT_SUCCESS(vrc))
+ vrc = callbackAdd(pCallbackWrite, &uContextID);
+ }
+
+ alock.release(); /* Drop the write lock again. */
+
+ if (RT_SUCCESS(vrc))
+ {
+ VBOXHGCMSVCPARM paParms[5];
+
+ int i = 0;
+ paParms[i++].setUInt32(uContextID);
+ paParms[i++].setUInt32(mData.mPID);
+ paParms[i++].setUInt32(uFlags);
+ paParms[i++].setPointer(pvData, cbData);
+ paParms[i++].setUInt32(cbData);
+
+ vrc = sendCommand(HOST_EXEC_SET_INPUT, i, paParms);
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ /*
+ * Let's wait for the process being started.
+ * Note: Be sure not keeping a AutoRead/WriteLock here.
+ */
+ LogFlowThisFunc(("Waiting for callback (%RU32ms) ...\n", uTimeoutMS));
+ vrc = pCallbackWrite->Wait(uTimeoutMS);
+ if (RT_SUCCESS(vrc)) /* Wait was successful, check for supplied information. */
+ {
+ int guestRc = pCallbackWrite->GetResultCode();
+ LogFlowThisFunc(("Callback returned rc=%Rrc, cbData=%RU32\n", guestRc, pCallbackWrite->GetDataSize()));
+
+ if (RT_SUCCESS(guestRc))
+ {
+ Assert(pCallbackWrite->GetDataSize() == sizeof(CALLBACKDATAEXECINSTATUS));
+ PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)pCallbackWrite->GetDataRaw();
+ AssertPtr(pData);
+
+ uint32_t cbWritten = 0;
+ switch (pData->u32Status)
+ {
+ case INPUT_STS_WRITTEN:
+ cbWritten = pData->cbProcessed;
+ break;
+
+ case INPUT_STS_ERROR:
+ vrc = pData->u32Flags; /** @todo Fix int vs. uint32_t! */
+ break;
+
+ case INPUT_STS_TERMINATED:
+ vrc = VERR_CANCELLED;
+ break;
+
+ case INPUT_STS_OVERFLOW:
+ vrc = VERR_BUFFER_OVERFLOW;
+ break;
+
+ default:
+ /* Silently skip unknown errors. */
+ break;
+ }
+
+ LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
+
+ if (pGuestRc)
+ *pGuestRc = guestRc;
+
+ if (puWritten)
+ *puWritten = cbWritten;
+
+ if (RT_FAILURE(guestRc))
+ vrc = VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+ }
+ }
+ }
+
+ alock.acquire();
+
+ int rc2 = callbackRemove(uContextID);
+ if (RT_SUCCESS(vrc))
+ vrc = rc2;
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+// implementation of public methods
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestProcess::Read(ULONG aHandle, ULONG aToRead, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ if (aToRead == 0)
+ return setError(E_INVALIDARG, tr("The size to read is zero"));
+ CheckComArgOutSafeArrayPointerValid(aData);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ com::SafeArray<BYTE> data((size_t)aToRead);
+ Assert(data.size() >= aToRead);
+
+ HRESULT hr = S_OK;
+
+ size_t cbRead; int guestRc;
+ int vrc = readData(aHandle, aToRead, aTimeoutMS, data.raw(), aToRead, &cbRead, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ if (data.size() != cbRead)
+ data.resize(cbRead);
+ data.detachTo(ComSafeArrayOutArg(aData));
+ }
+ else
+ {
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Reading from process \"%s\" (PID %RU32) failed: %Rrc"),
+ mData.mProcess.mCommand.c_str(), mData.mPID, vrc);
+ break;
+ }
+ }
+
+ LogFlowThisFunc(("rc=%Rrc, cbRead=%RU64\n", vrc, cbRead));
+
+ LogFlowFuncLeaveRC(vrc);
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::Terminate(void)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ HRESULT hr = S_OK;
+
+ int vrc = terminateProcess();
+ if (RT_FAILURE(vrc))
+ {
+ switch (vrc)
+ {
+ case VERR_NOT_IMPLEMENTED:
+ ReturnComNotImplemented();
+ break; /* Never reached. */
+
+ case VERR_NOT_SUPPORTED:
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Terminating process \"%s\" (PID %RU32) not supported by installed Guest Additions"),
+ mData.mProcess.mCommand.c_str(), mData.mPID);
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Terminating process \"%s\" (PID %RU32) failed: %Rrc"),
+ mData.mProcess.mCommand.c_str(), mData.mPID, vrc);
+ break;
+ }
+ }
+
+ AssertPtr(mData.mParent);
+ mData.mParent->processRemoveFromList(this);
+
+ /*
+ * Release autocaller before calling uninit.
+ */
+ autoCaller.release();
+
+ uninit();
+
+ LogFlowFuncLeaveRC(vrc);
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::WaitFor(ULONG aWaitFlags, ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aReason);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /*
+ * Note: Do not hold any locks here while waiting!
+ */
+ HRESULT hr = S_OK;
+
+ int guestRc; ProcessWaitResult_T waitResult;
+ int vrc = waitFor(aWaitFlags, aTimeoutMS, waitResult, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ *aReason = waitResult;
+ }
+ else
+ {
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ case VERR_TIMEOUT:
+ *aReason = ProcessWaitResult_Timeout;
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Waiting for process \"%s\" (PID %RU32) failed: %Rrc"),
+ mData.mProcess.mCommand.c_str(), mData.mPID, vrc);
+ break;
+ }
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::WaitForArray(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aReason);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /*
+ * Note: Do not hold any locks here while waiting!
+ */
+ uint32_t fWaitFor = ProcessWaitForFlag_None;
+ com::SafeArray<ProcessWaitForFlag_T> flags(ComSafeArrayInArg(aFlags));
+ for (size_t i = 0; i < flags.size(); i++)
+ fWaitFor |= flags[i];
+
+ return WaitFor(fWaitFor, aTimeoutMS, aReason);
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::Write(ULONG aHandle, ULONG aFlags,
+ ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aWritten);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ HRESULT hr = S_OK;
+
+ com::SafeArray<BYTE> data(ComSafeArrayInArg(aData)); int guestRc;
+ int vrc = writeData(aHandle, aFlags, data.raw(), data.size(), aTimeoutMS, (uint32_t*)aWritten, &guestRc);
+ if (RT_FAILURE(vrc))
+ {
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Writing to process \"%s\" (PID %RU32) failed: %Rrc"),
+ mData.mProcess.mCommand.c_str(), mData.mPID, vrc);
+ break;
+ }
+ }
+
+ LogFlowThisFunc(("rc=%Rrc, aWritten=%RU32\n", vrc, aWritten));
+
+ LogFlowFuncLeaveRC(vrc);
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::WriteArray(ULONG aHandle, ComSafeArrayIn(ProcessInputFlag_T, aFlags),
+ ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aWritten);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /*
+ * Note: Do not hold any locks here while writing!
+ */
+ ULONG fWrite = ProcessInputFlag_None;
+ com::SafeArray<ProcessInputFlag_T> flags(ComSafeArrayInArg(aFlags));
+ for (size_t i = 0; i < flags.size(); i++)
+ fWrite |= flags[i];
+
+ return Write(aHandle, fWrite, ComSafeArrayInArg(aData), aTimeoutMS, aWritten);
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GuestProcessTool::GuestProcessTool(void)
+ : pSession(NULL)
+{
+}
+
+GuestProcessTool::~GuestProcessTool(void)
+{
+ Terminate();
+}
+
+int GuestProcessTool::Init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
+ bool fAsync, int *pGuestRc)
+{
+ LogFlowThisFunc(("pGuestSession=%p, szCmd=%s, fAsync=%RTbool\n",
+ pGuestSession, startupInfo.mCommand.c_str(), fAsync));
+
+ AssertPtrReturn(pGuestSession, VERR_INVALID_POINTER);
+
+ pSession = pGuestSession;
+ mStartupInfo = startupInfo;
+
+ /* Make sure the process is hidden. */
+ mStartupInfo.mFlags |= ProcessCreateFlag_Hidden;
+
+ int vrc = pSession->processCreateExInteral(mStartupInfo, pProcess);
+ if (RT_SUCCESS(vrc))
+ vrc = fAsync ? pProcess->startProcessAsync() : pProcess->startProcess(pGuestRc);
+
+ if ( !fAsync
+ && ( pGuestRc
+ && RT_FAILURE(*pGuestRc)
+ )
+ )
+ {
+ vrc = VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestProcessTool::GetCurrentBlock(uint32_t uHandle, GuestProcessStreamBlock &strmBlock)
+{
+ const GuestProcessStream *pStream = NULL;
+ if (uHandle == OUTPUT_HANDLE_ID_STDOUT)
+ pStream = &mStdOut;
+ else if (uHandle == OUTPUT_HANDLE_ID_STDERR)
+ pStream = &mStdErr;
+
+ if (!pStream)
+ return VERR_INVALID_PARAMETER;
+
+ int vrc;
+ do
+ {
+ /* Try parsing the data to see if the current block is complete. */
+ vrc = mStdOut.ParseBlock(strmBlock);
+ if (strmBlock.GetCount())
+ break;
+ } while (RT_SUCCESS(vrc));
+
+ LogFlowThisFunc(("rc=%Rrc, %RU64 pairs\n",
+ vrc, strmBlock.GetCount()));
+ return vrc;
+}
+
+bool GuestProcessTool::IsRunning(void)
+{
+ AssertReturn(!pProcess.isNull(), true);
+
+ ProcessStatus_T procStatus = ProcessStatus_Undefined;
+ HRESULT hr = pProcess->COMGETTER(Status(&procStatus));
+ Assert(SUCCEEDED(hr));
+
+ if ( procStatus != ProcessStatus_Started
+ && procStatus != ProcessStatus_Paused
+ && procStatus != ProcessStatus_Terminating)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+int GuestProcessTool::TerminatedOk(LONG *pExitCode)
+{
+ Assert(!pProcess.isNull());
+ /* pExitCode is optional. */
+
+ if (!IsRunning())
+ {
+ LONG exitCode;
+ HRESULT hr = pProcess->COMGETTER(ExitCode(&exitCode));
+ Assert(SUCCEEDED(hr));
+
+ if (pExitCode)
+ *pExitCode = exitCode;
+
+ if (exitCode != 0)
+ return VERR_NOT_EQUAL; /** @todo Special guest control rc needed! */
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
+}
+
+int GuestProcessTool::Wait(uint32_t fFlags, int *pGuestRc)
+{
+ return WaitEx(fFlags, NULL /* pStreamBlock */, pGuestRc);
+}
+
+int GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc)
+{
+ LogFlowThisFunc(("pSession=%p, fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n",
+ pSession, fFlags, pStreamBlock, pGuestRc));
+
+ AssertPtrReturn(pSession, VERR_INVALID_POINTER);
+ Assert(!pProcess.isNull());
+ /* Other parameters are optional. */
+
+ /* Can we parse the next block without waiting? */
+ int vrc;
+ if (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK)
+ {
+ AssertPtr(pStreamBlock);
+ vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock);
+ if (RT_SUCCESS(vrc))
+ return vrc;
+ }
+
+ /* Do the waiting. */
+ uint32_t fWaitFlags = ProcessWaitForFlag_Terminate;
+ if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
+ fWaitFlags |= ProcessWaitForFlag_StdOut;
+ if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdErr)
+ fWaitFlags |= ProcessWaitForFlag_StdErr;
+
+ LogFlowFunc(("waitFlags=0x%x\n", fWaitFlags));
+
+ /** @todo Decrease timeout. */
+ uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS;
+
+ int guestRc;
+ bool fDone = false;
+
+ BYTE byBuf[_64K];
+ size_t cbRead;
+
+ bool fHandleStdOut = false;
+ bool fHandleStdErr = false;
+
+ ProcessWaitResult_T waitRes;
+ do
+ {
+ vrc = pProcess->waitFor(fWaitFlags,
+ uTimeoutMS, waitRes, &guestRc);
+ if (RT_FAILURE(vrc))
+ break;
+
+ switch (waitRes)
+ {
+ case ProcessWaitResult_StdIn:
+ vrc = VERR_NOT_IMPLEMENTED;
+ break;
+
+ case ProcessWaitResult_StdOut:
+ fHandleStdOut = true;
+ break;
+
+ case ProcessWaitResult_StdErr:
+ fHandleStdErr = true;
+ break;
+
+ case ProcessWaitResult_WaitFlagNotSupported:
+ if (fWaitFlags & ProcessWaitForFlag_StdOut)
+ fHandleStdOut = true;
+ if (fWaitFlags & ProcessWaitForFlag_StdErr)
+ fHandleStdErr = true;
+ /* Since waiting for stdout / stderr is not supported by the guest,
+ * wait a bit to not hog the CPU too much when polling for data. */
+ RTThreadSleep(1); /* Optional, don't check rc. */
+ break;
+
+ case ProcessWaitResult_Error:
+ vrc = VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+ break;
+
+ case ProcessWaitResult_Terminate:
+ fDone = true;
+ break;
+
+ case ProcessWaitResult_Timeout:
+ vrc = VERR_TIMEOUT;
+ break;
+
+ case ProcessWaitResult_Start:
+ case ProcessWaitResult_Status:
+ /* Not used here, just skip. */
+ break;
+
+ default:
+ AssertReleaseMsgFailed(("Unhandled process wait result %ld\n", waitRes));
+ break;
+ }
+
+ if (fHandleStdOut)
+ {
+ vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
+ uTimeoutMS, byBuf, sizeof(byBuf),
+ &cbRead, &guestRc);
+ if (RT_FAILURE(vrc))
+ break;
+
+ if (cbRead)
+ {
+ LogFlowThisFunc(("Received %RU64 bytes from stdout\n", cbRead));
+ vrc = mStdOut.AddData(byBuf, cbRead);
+
+ if ( RT_SUCCESS(vrc)
+ && (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK))
+ {
+ AssertPtr(pStreamBlock);
+ vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock);
+ if (RT_SUCCESS(vrc))
+ fDone = true;
+ }
+ }
+
+ fHandleStdOut = false;
+ }
+
+ if (fHandleStdErr)
+ {
+ vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDERR, sizeof(byBuf),
+ uTimeoutMS, byBuf, sizeof(byBuf),
+ &cbRead, &guestRc);
+ if (RT_FAILURE(vrc))
+ break;
+
+ if (cbRead)
+ {
+ LogFlowThisFunc(("Received %RU64 bytes from stderr\n", cbRead));
+ vrc = mStdErr.AddData(byBuf, cbRead);
+ }
+
+ fHandleStdErr = false;
+ }
+
+ } while (!fDone && RT_SUCCESS(vrc));
+
+ LogFlowThisFunc(("Loop ended with rc=%Rrc, guestRc=%Rrc, waitRes=%ld\n",
+ vrc, guestRc, waitRes));
+ if (pGuestRc)
+ *pGuestRc = guestRc;
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+void GuestProcessTool::Terminate(void)
+{
+ LogFlowThisFuncEnter();
+
+ if (!pProcess.isNull())
+ {
+ /** @todo Add pProcess.Terminate() here as soon as it's implemented. */
+
+ Assert(pSession);
+ int rc2 = pSession->processRemoveFromList(pProcess);
+ AssertRC(rc2);
+
+ pProcess.setNull();
+ }
+
+ LogFlowThisFuncLeave();
+}
+
diff --git a/src/VBox/Main/src-client/GuestSessionImpl.cpp b/src/VBox/Main/src-client/GuestSessionImpl.cpp
new file mode 100644
index 000000000..f24337c6e
--- /dev/null
+++ b/src/VBox/Main/src-client/GuestSessionImpl.cpp
@@ -0,0 +1,2055 @@
+
+/* $Id: GuestSessionImpl.cpp $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "GuestImpl.h"
+#include "GuestSessionImpl.h"
+#include "GuestCtrlImplPrivate.h"
+
+#include "Global.h"
+#include "AutoCaller.h"
+#include "ProgressImpl.h"
+
+#include <memory> /* For auto_ptr. */
+
+#include <iprt/env.h>
+#include <iprt/file.h> /* For CopyTo/From. */
+
+#include <VBox/com/array.h>
+#include <VBox/version.h>
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
+#include <VBox/log.h>
+
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR(GuestSession)
+
+HRESULT GuestSession::FinalConstruct(void)
+{
+ LogFlowThisFunc(("\n"));
+ return BaseFinalConstruct();
+}
+
+void GuestSession::FinalRelease(void)
+{
+ LogFlowThisFuncEnter();
+ uninit();
+ BaseFinalRelease();
+ LogFlowThisFuncLeave();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+int GuestSession::init(Guest *aGuest, ULONG aSessionID,
+ Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName)
+{
+ LogFlowThisFuncEnter();
+
+ AssertPtrReturn(aGuest, VERR_INVALID_POINTER);
+
+ /* Enclose the state transition NotReady->InInit->Ready. */
+ AutoInitSpan autoInitSpan(this);
+ AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
+
+ mData.mTimeout = 30 * 60 * 1000; /* Session timeout is 30 mins by default. */
+ mData.mParent = aGuest;
+ mData.mId = aSessionID;
+
+ mData.mCredentials.mUser = aUser;
+ mData.mCredentials.mPassword = aPassword;
+ mData.mCredentials.mDomain = aDomain;
+ mData.mName = aName;
+ mData.mNumObjects = 0;
+
+ /* Confirm a successful initialization when it's the case. */
+ autoInitSpan.setSucceeded();
+
+ LogFlowFuncLeaveRC(VINF_SUCCESS);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called from FinalRelease().
+ */
+void GuestSession::uninit(void)
+{
+ LogFlowThisFuncEnter();
+
+ /* Enclose the state transition Ready->InUninit->NotReady. */
+ AutoUninitSpan autoUninitSpan(this);
+ if (autoUninitSpan.uninitDone())
+ return;
+
+ int rc = VINF_SUCCESS;
+
+#ifndef VBOX_WITH_GUEST_CONTROL
+ LogFlowThisFunc(("Closing directories (%RU64 total)\n",
+ mData.mDirectories.size()));
+ for (SessionDirectories::iterator itDirs = mData.mDirectories.begin();
+ itDirs != mData.mDirectories.end(); ++itDirs)
+ {
+#ifdef DEBUG
+ ULONG cRefs = (*itDirs)->AddRef();
+ LogFlowThisFunc(("pFile=%p, cRefs=%RU32\n", (*itDirs), cRefs));
+ (*itDirs)->Release();
+#endif
+ (*itDirs)->uninit();
+ }
+ mData.mDirectories.clear();
+
+ LogFlowThisFunc(("Closing files (%RU64 total)\n",
+ mData.mFiles.size()));
+ for (SessionFiles::iterator itFiles = mData.mFiles.begin();
+ itFiles != mData.mFiles.end(); ++itFiles)
+ {
+#ifdef DEBUG
+ ULONG cRefs = (*itFiles)->AddRef();
+ LogFlowThisFunc(("pFile=%p, cRefs=%RU32\n", (*itFiles), cRefs));
+ (*itFiles)->Release();
+#endif
+ (*itFiles)->uninit();
+ }
+ mData.mFiles.clear();
+
+ LogFlowThisFunc(("Closing processes (%RU64 total)\n",
+ mData.mProcesses.size()));
+ for (SessionProcesses::iterator itProcs = mData.mProcesses.begin();
+ itProcs != mData.mProcesses.end(); ++itProcs)
+ {
+#ifdef DEBUG
+ ULONG cRefs = itProcs->second->AddRef();
+ LogFlowThisFunc(("pProcess=%p, cRefs=%RU32\n", itProcs->second, cRefs));
+ itProcs->second->Release();
+#endif
+ itProcs->second->uninit();
+ }
+ mData.mProcesses.clear();
+
+ LogFlowThisFunc(("mNumObjects=%RU32\n", mData.mNumObjects));
+#endif
+ LogFlowFuncLeaveRC(rc);
+}
+
+// implementation of public getters/setters for attributes
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestSession::COMGETTER(User)(BSTR *aUser)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aUser);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mCredentials.mUser.cloneTo(aUser);
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMGETTER(Domain)(BSTR *aDomain)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aDomain);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mCredentials.mDomain.cloneTo(aDomain);
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMGETTER(Name)(BSTR *aName)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aName);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mName.cloneTo(aName);
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMGETTER(Id)(ULONG *aId)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aId);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aId = mData.mId;
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMGETTER(Timeout)(ULONG *aTimeout)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aTimeout);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aTimeout = mData.mTimeout;
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMSETTER(Timeout)(ULONG aTimeout)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mTimeout = aTimeout;
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMGETTER(Environment)(ComSafeArrayOut(BSTR, aEnvironment))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutSafeArrayPointerValid(aEnvironment);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ size_t cEnvVars = mData.mEnvironment.Size();
+ LogFlowThisFunc(("%s cEnvVars=%RU32\n", mData.mName.c_str(), cEnvVars));
+ com::SafeArray<BSTR> environment(cEnvVars);
+
+ for (size_t i = 0; i < cEnvVars; i++)
+ {
+ Bstr strEnv(mData.mEnvironment.Get(i));
+ strEnv.cloneTo(&environment[i]);
+ }
+ environment.detachTo(ComSafeArrayOutArg(aEnvironment));
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMSETTER(Environment)(ComSafeArrayIn(IN_BSTR, aValues))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aValues));
+
+ int rc = VINF_SUCCESS;
+ for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
+ {
+ Utf8Str strEnv(environment[i]);
+ if (!strEnv.isEmpty()) /* Silently skip empty entries. */
+ rc = mData.mEnvironment.Set(strEnv);
+ }
+
+ HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
+ LogFlowFuncLeaveRC(hr);
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMGETTER(Processes)(ComSafeArrayOut(IGuestProcess *, aProcesses))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutSafeArrayPointerValid(aProcesses);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ SafeIfaceArray<IGuestProcess> collection(mData.mProcesses);
+ collection.detachTo(ComSafeArrayOutArg(aProcesses));
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMGETTER(Directories)(ComSafeArrayOut(IGuestDirectory *, aDirectories))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutSafeArrayPointerValid(aDirectories);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ SafeIfaceArray<IGuestDirectory> collection(mData.mDirectories);
+ collection.detachTo(ComSafeArrayOutArg(aDirectories));
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::COMGETTER(Files)(ComSafeArrayOut(IGuestFile *, aFiles))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutSafeArrayPointerValid(aFiles);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ SafeIfaceArray<IGuestFile> collection(mData.mFiles);
+ collection.detachTo(ComSafeArrayOutArg(aFiles));
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+// private methods
+/////////////////////////////////////////////////////////////////////////////
+
+int GuestSession::directoryRemoveFromList(GuestDirectory *pDirectory)
+{
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ for (SessionDirectories::iterator itDirs = mData.mDirectories.begin();
+ itDirs != mData.mDirectories.end(); ++itDirs)
+ {
+ if (pDirectory == (*itDirs))
+ {
+ Bstr strName;
+ HRESULT hr = (*itDirs)->COMGETTER(DirectoryName)(strName.asOutParam());
+ ComAssertComRC(hr);
+
+ Assert(mData.mDirectories.size());
+ LogFlowFunc(("Removing directory \"%s\" (Session: %RU32) (now total %ld directories)\n",
+ Utf8Str(strName).c_str(), mData.mId, mData.mDirectories.size() - 1));
+
+ mData.mDirectories.erase(itDirs);
+ return VINF_SUCCESS;
+ }
+ }
+
+ return VERR_NOT_FOUND;
+}
+
+int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc)
+{
+ LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
+ strPath.c_str(), uMode, uFlags));
+
+ GuestProcessStartupInfo procInfo;
+ procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
+ procInfo.mFlags = ProcessCreateFlag_Hidden;
+
+ int vrc = VINF_SUCCESS;
+
+ /* Construct arguments. */
+ if (uFlags & DirectoryCreateFlag_Parents)
+ procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
+ if (uMode)
+ {
+ procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
+
+ char szMode[16];
+ if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
+ {
+ procInfo.mArguments.push_back(Utf8Str(szMode));
+ }
+ else
+ vrc = VERR_BUFFER_OVERFLOW;
+ }
+ procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
+
+ int guestRc;
+ if (RT_SUCCESS(vrc))
+ {
+ GuestProcessTool procTool;
+ vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ if (RT_SUCCESS(guestRc))
+ vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ if (RT_SUCCESS(guestRc))
+ guestRc = procTool.TerminatedOk(NULL /* Exit code */);
+ }
+
+ if (pGuestRc)
+ *pGuestRc = guestRc;
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ if (RT_FAILURE(vrc))
+ return vrc;
+ return RT_SUCCESS(guestRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+}
+
+int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
+{
+ LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
+
+ int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ vrc = objData.mType == FsObjType_Directory
+ ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestSession::objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath,
+ bool fDirectory, const Utf8Str &strName, int *pGuestRc)
+{
+ GuestProcessStartupInfo procInfo;
+ procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKTEMP);
+ procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
+ procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
+ if (fDirectory)
+ procInfo.mArguments.push_back(Utf8Str("-d"));
+ if (strPath.length()) /* Otherwise use /tmp or equivalent. */
+ {
+ procInfo.mArguments.push_back(Utf8Str("-t"));
+ procInfo.mArguments.push_back(strPath);
+ }
+ procInfo.mArguments.push_back(strTemplate);
+
+ GuestProcessTool procTool; int guestRc;
+ int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ if (RT_SUCCESS(guestRc))
+ vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
+ }
+
+ if (RT_SUCCESS(vrc))
+ {
+ if (RT_SUCCESS(guestRc))
+ guestRc = procTool.TerminatedOk(NULL /* Exit code */);
+ }
+
+ if (pGuestRc)
+ *pGuestRc = guestRc;
+
+ if (RT_FAILURE(vrc))
+ return vrc;
+ return RT_SUCCESS(guestRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+}
+
+int GuestSession::directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter,
+ uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory)
+{
+ LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
+ strPath.c_str(), strFilter.c_str(), uFlags));
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ /* Create the directory object. */
+ HRESULT hr = pDirectory.createObject();
+ if (FAILED(hr))
+ return VERR_COM_UNEXPECTED;
+
+ int vrc = pDirectory->init(this /* Parent */,
+ strPath, strFilter, uFlags);
+ if (RT_FAILURE(vrc))
+ return vrc;
+
+ /* Add the created directory to our vector. */
+ mData.mDirectories.push_back(pDirectory);
+
+ LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
+ strPath.c_str(), mData.mId));
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestSession::dispatchToProcess(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData)
+{
+ LogFlowFuncEnter();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ uint32_t uProcessID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(uContextID);
+#ifdef DEBUG
+ LogFlowFunc(("uProcessID=%RU32 (%RU32 total)\n",
+ uProcessID, mData.mProcesses.size()));
+#endif
+ int rc;
+ SessionProcesses::const_iterator itProc
+ = mData.mProcesses.find(uProcessID);
+ if (itProc != mData.mProcesses.end())
+ {
+ ComObjPtr<GuestProcess> pProcess(itProc->second);
+ Assert(!pProcess.isNull());
+
+ alock.release();
+ rc = pProcess->callbackDispatcher(uContextID, uFunction, pvData, cbData);
+ }
+ else
+ rc = VERR_NOT_FOUND;
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+int GuestSession::fileRemoveFromList(GuestFile *pFile)
+{
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ for (SessionFiles::iterator itFiles = mData.mFiles.begin();
+ itFiles != mData.mFiles.end(); ++itFiles)
+ {
+ if (pFile == (*itFiles))
+ {
+ Bstr strName;
+ HRESULT hr = (*itFiles)->COMGETTER(FileName)(strName.asOutParam());
+ ComAssertComRC(hr);
+
+ Assert(mData.mNumObjects);
+ LogFlowThisFunc(("Removing file \"%s\" (Session: %RU32) (now total %ld files, %ld objects)\n",
+ Utf8Str(strName).c_str(), mData.mId, mData.mFiles.size() - 1, mData.mNumObjects - 1));
+#ifdef DEBUG
+ ULONG cRefs = pFile->AddRef();
+ LogFlowThisFunc(("pObject=%p, cRefs=%RU32\n", pFile, cRefs));
+ pFile->Release();
+#endif
+ mData.mFiles.erase(itFiles);
+ mData.mNumObjects--;
+ return VINF_SUCCESS;
+ }
+ }
+
+ return VERR_NOT_FOUND;
+}
+
+int GuestSession::fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc)
+{
+ GuestProcessStartupInfo procInfo;
+ GuestProcessStream streamOut;
+
+ procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_RM);
+ procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
+ procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
+ procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
+
+ GuestProcessTool procTool; int guestRc;
+ int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
+ if (RT_SUCCESS(vrc))
+ vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
+
+ if (RT_SUCCESS(vrc))
+ {
+ if (RT_SUCCESS(guestRc))
+ guestRc = procTool.TerminatedOk(NULL /* Exit code */);
+ }
+
+ if (pGuestRc)
+ *pGuestRc = guestRc;
+
+ if (RT_FAILURE(vrc))
+ return vrc;
+ return RT_SUCCESS(guestRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+}
+
+int GuestSession::fileOpenInternal(const Utf8Str &strPath, const Utf8Str &strOpenMode, const Utf8Str &strDisposition,
+ uint32_t uCreationMode, int64_t iOffset, ComObjPtr<GuestFile> &pFile, int *pGuestRc)
+{
+ LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, iOffset=%RI64\n",
+ strPath.c_str(), strOpenMode.c_str(), strDisposition.c_str(), uCreationMode, iOffset));
+
+ /* Create the directory object. */
+ HRESULT hr = pFile.createObject();
+ if (FAILED(hr))
+ return VERR_COM_UNEXPECTED;
+
+ int vrc = pFile->init(this /* Parent */,
+ strPath, strOpenMode, strDisposition, uCreationMode, iOffset, pGuestRc);
+ if (RT_FAILURE(vrc))
+ return vrc;
+ /** @todo Handle guestRc. */
+
+ /* Add the created directory to our vector. */
+ mData.mFiles.push_back(pFile);
+ mData.mNumObjects++;
+ Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
+
+ LogFlowFunc(("Added new file \"%s\" (Session: %RU32) (now total %ld files, %ld objects)\n",
+ strPath.c_str(), mData.mId, mData.mProcesses.size(), mData.mNumObjects));
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestSession::fileQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
+{
+ LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
+
+ int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ vrc = objData.mType == FsObjType_File
+ ? VINF_SUCCESS : VERR_NOT_A_FILE;
+ }
+
+ LogFlowFuncLeaveRC(vrc);
+ return vrc;
+}
+
+int GuestSession::fileQuerySizeInternal(const Utf8Str &strPath, int64_t *pllSize, int *pGuestRc)
+{
+ AssertPtrReturn(pllSize, VERR_INVALID_POINTER);
+
+ GuestFsObjData objData;
+ int vrc = fileQueryInfoInternal(strPath, objData, pGuestRc);
+ if (RT_SUCCESS(vrc))
+ *pllSize = objData.mObjectSize;
+
+ return vrc;
+}
+
+int GuestSession::fsQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
+{
+ LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
+
+ /** @todo Merge this with IGuestFile::queryInfo(). */
+ GuestProcessStartupInfo procInfo;
+ procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_STAT);
+ procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
+
+ /* Construct arguments. */
+ procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
+ procInfo.mArguments.push_back(strPath);
+
+ GuestProcessTool procTool; int guestRc;
+ int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
+ if (RT_SUCCESS(vrc))
+ vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ guestRc = procTool.TerminatedOk(NULL /* Exit code */);
+ if (RT_SUCCESS(guestRc))
+ {
+ GuestProcessStreamBlock curBlock;
+ vrc = procTool.GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, curBlock);
+ /** @todo Check for more / validate blocks! */
+ if (RT_SUCCESS(vrc))
+ vrc = objData.FromStat(curBlock);
+ }
+ }
+
+ if (pGuestRc)
+ *pGuestRc = guestRc;
+
+ LogFlowFuncLeaveRC(vrc);
+ if (RT_FAILURE(vrc))
+ return vrc;
+ return RT_SUCCESS(guestRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
+}
+
+const GuestCredentials& GuestSession::getCredentials(void)
+{
+ return mData.mCredentials;
+}
+
+const GuestEnvironment& GuestSession::getEnvironment(void)
+{
+ return mData.mEnvironment;
+}
+
+Utf8Str GuestSession::getName(void)
+{
+ return mData.mName;
+}
+
+int GuestSession::processRemoveFromList(GuestProcess *pProcess)
+{
+ LogFlowThisFuncEnter();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ int rc = VERR_NOT_FOUND;
+
+ ULONG uPID;
+ HRESULT hr = pProcess->COMGETTER(PID)(&uPID);
+
+ LogFlowFunc(("Closing process (PID=%RU32) ...\n", uPID));
+
+ for (SessionProcesses::iterator itProcs = mData.mProcesses.begin();
+ itProcs != mData.mProcesses.end(); ++itProcs)
+ {
+ if (pProcess == itProcs->second)
+ {
+ GuestProcess *pCurProc = itProcs->second;
+ AssertPtr(pCurProc);
+
+ hr = pCurProc->COMGETTER(PID)(&uPID);
+ ComAssertComRC(hr);
+
+ Assert(mData.mNumObjects);
+ LogFlowFunc(("Removing process (Session: %RU32) with process ID=%RU32, guest PID=%RU32 (now total %ld processes, %ld objects)\n",
+ mData.mId, pCurProc->getProcessID(), uPID, mData.mProcesses.size() - 1, mData.mNumObjects - 1));
+
+ mData.mProcesses.erase(itProcs);
+ mData.mNumObjects--;
+
+ rc = VINF_SUCCESS;
+ break;
+ }
+ }
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+/**
+ * Creates but does *not* start the process yet. See GuestProcess::startProcess() or
+ * GuestProcess::startProcessAsync() for that.
+ *
+ * @return IPRT status code.
+ * @param procInfo
+ * @param pProcess
+ */
+int GuestSession::processCreateExInteral(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProcess)
+{
+ LogFlowFunc(("mCmd=%s, mFlags=%x, mTimeoutMS=%RU32\n",
+ procInfo.mCommand.c_str(), procInfo.mFlags, procInfo.mTimeoutMS));
+#ifdef DEBUG
+ if (procInfo.mArguments.size())
+ {
+ LogFlowFunc(("Arguments:"));
+ ProcessArguments::const_iterator it = procInfo.mArguments.begin();
+ while (it != procInfo.mArguments.end())
+ {
+ LogFlow((" %s", (*it).c_str()));
+ it++;
+ }
+ LogFlow(("\n"));
+ }
+#endif
+
+ /* Validate flags. */
+ if (procInfo.mFlags)
+ {
+ if ( !(procInfo.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
+ && !(procInfo.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
+ && !(procInfo.mFlags & ProcessCreateFlag_Hidden)
+ && !(procInfo.mFlags & ProcessCreateFlag_NoProfile)
+ && !(procInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
+ && !(procInfo.mFlags & ProcessCreateFlag_WaitForStdErr))
+ {
+ return VERR_INVALID_PARAMETER;
+ }
+ }
+
+ /* Adjust timeout. If set to 0, we define
+ * an infinite timeout. */
+ if (procInfo.mTimeoutMS == 0)
+ procInfo.mTimeoutMS = UINT32_MAX;
+
+ /** @tood Implement process priority + affinity. */
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ int rc = VERR_MAX_PROCS_REACHED;
+ if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS)
+ return rc;
+
+ /* Create a new (host-based) process ID and assign it. */
+ uint32_t uNewProcessID = 0;
+ ULONG uTries = 0;
+
+ for (;;)
+ {
+ /* Is the context ID already used? */
+ if (!processExists(uNewProcessID, NULL /* pProgress */))
+ {
+ /* Callback with context ID was not found. This means
+ * we can use this context ID for our new callback we want
+ * to add below. */
+ rc = VINF_SUCCESS;
+ break;
+ }
+ uNewProcessID++;
+ if (uNewProcessID == VBOX_GUESTCTRL_MAX_OBJECTS)
+ uNewProcessID = 0;
+
+ if (++uTries == UINT32_MAX)
+ break; /* Don't try too hard. */
+ }
+
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /* Create the process object. */
+ HRESULT hr = pProcess.createObject();
+ if (FAILED(hr))
+ return VERR_COM_UNEXPECTED;
+
+ rc = pProcess->init(mData.mParent->getConsole() /* Console */, this /* Session */,
+ uNewProcessID, procInfo);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /* Add the created process to our map. */
+ mData.mProcesses[uNewProcessID] = pProcess;
+ mData.mNumObjects++;
+ Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
+
+ LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32 (now total %ld processes, %ld objects)\n",
+ mData.mId, uNewProcessID, mData.mProcesses.size(), mData.mNumObjects));
+
+ return rc;
+}
+
+inline bool GuestSession::processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess)
+{
+ SessionProcesses::const_iterator it = mData.mProcesses.find(uProcessID);
+ if (it != mData.mProcesses.end())
+ {
+ if (pProcess)
+ *pProcess = it->second;
+ return true;
+ }
+ return false;
+}
+
+inline int GuestSession::processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess)
+{
+ AssertReturn(uPID, false);
+ /* pProcess is optional. */
+
+ SessionProcesses::iterator itProcs = mData.mProcesses.begin();
+ for (; itProcs != mData.mProcesses.end(); itProcs++)
+ {
+ ComObjPtr<GuestProcess> pCurProc = itProcs->second;
+ AutoCaller procCaller(pCurProc);
+ if (procCaller.rc())
+ return VERR_COM_INVALID_OBJECT_STATE;
+
+ ULONG uCurPID;
+ HRESULT hr = pCurProc->COMGETTER(PID)(&uCurPID);
+ ComAssertComRC(hr);
+
+ if (uCurPID == uPID)
+ {
+ if (pProcess)
+ *pProcess = pCurProc;
+ return VINF_SUCCESS;
+ }
+ }
+
+ return VERR_NOT_FOUND;
+}
+
+int GuestSession::startTaskAsync(const Utf8Str &strTaskDesc,
+ GuestSessionTask *pTask, ComObjPtr<Progress> &pProgress)
+{
+ LogFlowThisFunc(("strTaskDesc=%s, pTask=%p\n", strTaskDesc.c_str(), pTask));
+
+ AssertPtrReturn(pTask, VERR_INVALID_POINTER);
+
+ /* Create the progress object. */
+ HRESULT hr = pProgress.createObject();
+ if (FAILED(hr))
+ return VERR_COM_UNEXPECTED;
+
+ hr = pProgress->init(static_cast<IGuestSession*>(this),
+ Bstr(strTaskDesc).raw(),
+ TRUE /* aCancelable */);
+ if (FAILED(hr))
+ return VERR_COM_UNEXPECTED;
+
+ /* Initialize our worker task. */
+ std::auto_ptr<GuestSessionTask> task(pTask);
+
+ int rc = task->RunAsync(strTaskDesc, pProgress);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /* Don't destruct on success. */
+ task.release();
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+/**
+ * Queries/collects information prior to establishing a guest session.
+ * This is necessary to know which guest control protocol version to use,
+ * among other things (later).
+ *
+ * @return IPRT status code.
+ */
+int GuestSession::queryInfo(void)
+{
+#if 1
+ /* Since the new functions were not implemented yet, force Main to use protocol ver 1. */
+ mData.mProtocolVersion = 1;
+#else
+ /*
+ * Try querying the guest control protocol version running on the guest.
+ * This is done using the Guest Additions version
+ */
+ ComObjPtr<Guest> pGuest = mData.mParent;
+ Assert(!pGuest.isNull());
+
+ uint32_t uVerAdditions = pGuest->getAdditionsVersion();
+ mData.mProtocolVersion = ( VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions) >= 4
+ && VBOX_FULL_VERSION_GET_MINOR(uVerAdditions) >= 2) /** @todo What's about v5.0 ? */
+ ? 2 /* Guest control 2.0. */
+ : 1; /* Legacy guest control (VBox < 4.2). */
+ /* Build revision is ignored. */
+
+ /* Tell the user but don't bitch too often. */
+ static short s_gctrlLegacyWarning = 0;
+ if (s_gctrlLegacyWarning++ < 3) /** @todo Find a bit nicer text. */
+ LogRel((tr("Warning: Guest Additions are older (%ld.%ld) than host capabilities for guest control, please upgrade them. Using protocol version %ld now\n"),
+ VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions), VBOX_FULL_VERSION_GET_MINOR(uVerAdditions), mData.mProtocolVersion));
+#endif
+ return VINF_SUCCESS;
+}
+
+// implementation of public methods
+/////////////////////////////////////////////////////////////////////////////
+
+STDMETHODIMP GuestSession::Close(void)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /* Remove ourselves from the session list. */
+ mData.mParent->sessionRemove(this);
+
+ /*
+ * Release autocaller before calling uninit.
+ */
+ autoCaller.release();
+
+ uninit();
+
+ LogFlowFuncLeave();
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::CopyFrom(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ CheckComArgStrNotEmptyOrNull(aSource);
+ CheckComArgStrNotEmptyOrNull(aDest);
+ CheckComArgOutPointerValid(aProgress);
+
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
+ return setError(E_INVALIDARG, tr("No source specified"));
+ if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
+ return setError(E_INVALIDARG, tr("No destination specified"));
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ uint32_t fFlags = CopyFileFlag_None;
+ if (aFlags)
+ {
+ com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
+ for (size_t i = 0; i < flags.size(); i++)
+ fFlags |= flags[i];
+ }
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ HRESULT hr = S_OK;
+
+ try
+ {
+ ComObjPtr<Progress> pProgress;
+ SessionTaskCopyFrom *pTask = new SessionTaskCopyFrom(this /* GuestSession */,
+ Utf8Str(aSource), Utf8Str(aDest), fFlags);
+ int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from guest to \"%ls\" on the host"), aSource, aDest),
+ pTask, pProgress);
+ if (RT_SUCCESS(rc))
+ {
+ /* Return progress to the caller. */
+ hr = pProgress.queryInterfaceTo(aProgress);
+ }
+ else
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Starting task for copying file \"%ls\" from guest to \"%ls\" on the host failed: %Rrc"), rc);
+ }
+ catch(std::bad_alloc &)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::CopyTo(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ CheckComArgStrNotEmptyOrNull(aSource);
+ CheckComArgStrNotEmptyOrNull(aDest);
+ CheckComArgOutPointerValid(aProgress);
+
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
+ return setError(E_INVALIDARG, tr("No source specified"));
+ if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
+ return setError(E_INVALIDARG, tr("No destination specified"));
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ uint32_t fFlags = CopyFileFlag_None;
+ if (aFlags)
+ {
+ com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
+ for (size_t i = 0; i < flags.size(); i++)
+ fFlags |= flags[i];
+ }
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ HRESULT hr = S_OK;
+
+ try
+ {
+ ComObjPtr<Progress> pProgress;
+ SessionTaskCopyTo *pTask = new SessionTaskCopyTo(this /* GuestSession */,
+ Utf8Str(aSource), Utf8Str(aDest), fFlags);
+ AssertPtrReturn(pTask, VERR_NO_MEMORY);
+ int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from host to \"%ls\" on the guest"), aSource, aDest),
+ pTask, pProgress);
+ if (RT_SUCCESS(rc))
+ {
+ /* Return progress to the caller. */
+ hr = pProgress.queryInterfaceTo(aProgress);
+ }
+ else
+ hr = setError(VBOX_E_IPRT_ERROR,
+ tr("Starting task for copying file \"%ls\" from host to \"%ls\" on the guest failed: %Rrc"), rc);
+ }
+ catch(std::bad_alloc &)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectoryCreate(IN_BSTR aPath, ULONG aMode,
+ ComSafeArrayIn(DirectoryCreateFlag_T, aFlags))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No directory to create specified"));
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ uint32_t fFlags = DirectoryCreateFlag_None;
+ if (aFlags)
+ {
+ com::SafeArray<DirectoryCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
+ for (size_t i = 0; i < flags.size(); i++)
+ fFlags |= flags[i];
+
+ if (fFlags)
+ {
+ if (!(fFlags & DirectoryCreateFlag_Parents))
+ return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), fFlags);
+ }
+ }
+
+ HRESULT hr = S_OK;
+
+ ComObjPtr <GuestDirectory> pDirectory; int guestRc;
+ int rc = directoryCreateInternal(Utf8Str(aPath), (uint32_t)aMode, fFlags, &guestRc);
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ case VERR_INVALID_PARAMETER:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Invalid parameters given"));
+ break;
+
+ case VERR_BROKEN_PIPE:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Unexpectedly aborted"));
+ break;
+
+ case VERR_CANT_CREATE:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Could not create directory"));
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: %Rrc"), rc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectoryCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, BSTR *aDirectory)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aTemplate) == NULL || *(aTemplate) == '\0'))
+ return setError(E_INVALIDARG, tr("No template specified"));
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No directory name specified"));
+ CheckComArgOutPointerValid(aDirectory);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ HRESULT hr = S_OK;
+
+ Utf8Str strName; int guestRc;
+ int rc = objectCreateTempInternal(Utf8Str(aTemplate),
+ Utf8Str(aPath),
+ true /* Directory */, strName, &guestRc);
+ if (RT_SUCCESS(rc))
+ {
+ strName.cloneTo(aDirectory);
+ }
+ else
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Temporary directory creation \"%s\" with template \"%s\" failed: %Rrc"),
+ Utf8Str(aPath).c_str(), Utf8Str(aTemplate).c_str(), rc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectoryExists(IN_BSTR aPath, BOOL *aExists)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No directory to check existence for specified"));
+ CheckComArgOutPointerValid(aExists);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ HRESULT hr = S_OK;
+
+ GuestFsObjData objData; int guestRc;
+ int rc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
+ if (RT_SUCCESS(rc))
+ {
+ *aExists = objData.mType == FsObjType_Directory;
+ }
+ else
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory existence \"%s\" failed: %Rrc"),
+ Utf8Str(aPath).c_str(), rc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectoryOpen(IN_BSTR aPath, IN_BSTR aFilter, ComSafeArrayIn(DirectoryOpenFlag_T, aFlags), IGuestDirectory **aDirectory)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No directory to open specified"));
+ if (RT_UNLIKELY((aFilter) != NULL && *(aFilter) != '\0'))
+ return setError(E_INVALIDARG, tr("Directory filters are not implemented yet"));
+ CheckComArgOutPointerValid(aDirectory);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ uint32_t fFlags = DirectoryOpenFlag_None;
+ if (aFlags)
+ {
+ com::SafeArray<DirectoryOpenFlag_T> flags(ComSafeArrayInArg(aFlags));
+ for (size_t i = 0; i < flags.size(); i++)
+ fFlags |= flags[i];
+
+ if (fFlags)
+ return setError(E_INVALIDARG, tr("Open flags (%#x) not implemented yet"), fFlags);
+ }
+
+ HRESULT hr = S_OK;
+
+ ComObjPtr <GuestDirectory> pDirectory;
+ int rc = directoryOpenInternal(Utf8Str(aPath), Utf8Str(aFilter), fFlags, pDirectory);
+ if (RT_SUCCESS(rc))
+ {
+ /* Return directory object to the caller. */
+ hr = pDirectory.queryInterfaceTo(aDirectory);
+ }
+ else
+ {
+ switch (rc)
+ {
+ case VERR_INVALID_PARAMETER:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed; invalid parameters given",
+ Utf8Str(aPath).c_str()));
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed: %Rrc"),
+ Utf8Str(aPath).c_str(),rc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectoryQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No directory to query information for specified"));
+ CheckComArgOutPointerValid(aInfo);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ HRESULT hr = S_OK;
+
+ GuestFsObjData objData; int guestRc;
+ int vrc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ if (objData.mType == FsObjType_Directory)
+ {
+ ComObjPtr<GuestFsObjInfo> pFsObjInfo;
+ hr = pFsObjInfo.createObject();
+ if (FAILED(hr)) return hr;
+
+ vrc = pFsObjInfo->init(objData);
+ if (RT_SUCCESS(vrc))
+ {
+ hr = pFsObjInfo.queryInterfaceTo(aInfo);
+ if (FAILED(hr)) return hr;
+ }
+ }
+ }
+
+ if (RT_FAILURE(vrc))
+ {
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ case VERR_NOT_A_DIRECTORY:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Element \"%s\" exists but is not a directory",
+ Utf8Str(aPath).c_str()));
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory information for \"%s\" failed: %Rrc"),
+ Utf8Str(aPath).c_str(), vrc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectoryRemove(IN_BSTR aPath)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectoryRemoveRecursive(IN_BSTR aPath, ComSafeArrayIn(DirectoryRemoveRecFlag_T, aFlags), IProgress **aProgress)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectoryRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::DirectorySetACL(IN_BSTR aPath, IN_BSTR aACL)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::EnvironmentClear(void)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mEnvironment.Clear();
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::EnvironmentGet(IN_BSTR aName, BSTR *aValue)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
+ return setError(E_INVALIDARG, tr("No value name specified"));
+
+ CheckComArgOutPointerValid(aValue);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ Bstr strValue(mData.mEnvironment.Get(Utf8Str(aName)));
+ strValue.cloneTo(aValue);
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::EnvironmentSet(IN_BSTR aName, IN_BSTR aValue)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
+ return setError(E_INVALIDARG, tr("No value name specified"));
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ int rc = mData.mEnvironment.Set(Utf8Str(aName), Utf8Str(aValue));
+
+ HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
+ LogFlowFuncLeaveRC(hr);
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::EnvironmentUnset(IN_BSTR aName)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ mData.mEnvironment.Unset(Utf8Str(aName));
+
+ LogFlowFuncLeaveRC(S_OK);
+ return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::FileCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, IGuestFile **aFile)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::FileExists(IN_BSTR aPath, BOOL *aExists)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No file to check existence for specified"));
+ CheckComArgOutPointerValid(aExists);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ GuestFsObjData objData; int guestRc;
+ int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ *aExists = TRUE;
+ return S_OK;
+ }
+
+ HRESULT hr = S_OK;
+
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ case VERR_NOT_A_FILE:
+ *aExists = FALSE;
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information for \"%s\" failed: %Rrc"),
+ Utf8Str(aPath).c_str(), vrc);
+ break;
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::FileRemove(IN_BSTR aPath)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No file to remove specified"));
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ HRESULT hr = S_OK;
+
+ int guestRc;
+ int vrc = fileRemoveInternal(Utf8Str(aPath), &guestRc);
+ if (RT_FAILURE(vrc))
+ {
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Removing file \"%s\" failed: %Rrc"),
+ Utf8Str(aPath).c_str(), vrc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::FileOpen(IN_BSTR aPath, IN_BSTR aOpenMode, IN_BSTR aDisposition, ULONG aCreationMode, LONG64 aOffset, IGuestFile **aFile)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No file to open specified"));
+ if (RT_UNLIKELY((aOpenMode) == NULL || *(aOpenMode) == '\0'))
+ return setError(E_INVALIDARG, tr("No open mode specified"));
+ if (RT_UNLIKELY((aDisposition) == NULL || *(aDisposition) == '\0'))
+ return setError(E_INVALIDARG, tr("No disposition mode specified"));
+
+ CheckComArgOutPointerValid(aFile);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /** @todo Validate open mode. */
+ /** @todo Validate disposition mode. */
+
+ /** @todo Validate creation mode. */
+ uint32_t uCreationMode = 0;
+
+ HRESULT hr = S_OK;
+
+ ComObjPtr <GuestFile> pFile; int guestRc;
+ int vrc = fileOpenInternal(Utf8Str(aPath), Utf8Str(aOpenMode), Utf8Str(aDisposition),
+ aCreationMode, aOffset, pFile, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ /* Return directory object to the caller. */
+ hr = pFile.queryInterfaceTo(aFile);
+ }
+ else
+ {
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Opening file \"%s\" failed: %Rrc"),
+ Utf8Str(aPath).c_str(), vrc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::FileQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No file to query information for specified"));
+ CheckComArgOutPointerValid(aInfo);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ HRESULT hr = S_OK;
+
+ GuestFsObjData objData; int guestRc;
+ int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ ComObjPtr<GuestFsObjInfo> pFsObjInfo;
+ hr = pFsObjInfo.createObject();
+ if (FAILED(hr)) return hr;
+
+ vrc = pFsObjInfo->init(objData);
+ if (RT_SUCCESS(vrc))
+ {
+ hr = pFsObjInfo.queryInterfaceTo(aInfo);
+ if (FAILED(hr)) return hr;
+ }
+ }
+
+ if (RT_FAILURE(vrc))
+ {
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ case VERR_NOT_A_FILE:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Element exists but is not a file"));
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information failed: %Rrc"), vrc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::FileQuerySize(IN_BSTR aPath, LONG64 *aSize)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
+ return setError(E_INVALIDARG, tr("No file to query size for specified"));
+ CheckComArgOutPointerValid(aSize);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ HRESULT hr = S_OK;
+
+ int64_t llSize; int guestRc;
+ int vrc = fileQuerySizeInternal(Utf8Str(aPath), &llSize, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ *aSize = llSize;
+ }
+ else
+ {
+ switch (vrc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ hr = GuestProcess::setErrorExternal(this, guestRc);
+ break;
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file size failed: %Rrc"), vrc);
+ break;
+ }
+ }
+
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::FileRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::FileSetACL(IN_BSTR aPath, IN_BSTR aACL)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::ProcessCreate(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
+ ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, IGuestProcess **aProcess)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ com::SafeArray<LONG> affinity;
+
+ return ProcessCreateEx(aCommand, ComSafeArrayInArg(aArguments), ComSafeArrayInArg(aEnvironment),
+ ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess);
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::ProcessCreateEx(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
+ ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
+ ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity),
+ IGuestProcess **aProcess)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ if (RT_UNLIKELY((aCommand) == NULL || *(aCommand) == '\0'))
+ return setError(E_INVALIDARG, tr("No command to execute specified"));
+ CheckComArgOutPointerValid(aProcess);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ GuestProcessStartupInfo procInfo;
+ procInfo.mCommand = Utf8Str(aCommand);
+
+ if (aArguments)
+ {
+ com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments));
+ for (size_t i = 0; i < arguments.size(); i++)
+ procInfo.mArguments.push_back(Utf8Str(arguments[i]));
+ }
+
+ int rc = VINF_SUCCESS;
+
+ /*
+ * Create the process environment:
+ * - Apply the session environment in a first step, and
+ * - Apply environment variables specified by this call to
+ * have the chance of overwriting/deleting session entries.
+ */
+ procInfo.mEnvironment = mData.mEnvironment; /* Apply original session environment. */
+
+ if (aEnvironment)
+ {
+ com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment));
+ for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
+ rc = procInfo.mEnvironment.Set(Utf8Str(environment[i]));
+ }
+
+ HRESULT hr = S_OK;
+
+ if (RT_SUCCESS(rc))
+ {
+ if (aFlags)
+ {
+ com::SafeArray<ProcessCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
+ for (size_t i = 0; i < flags.size(); i++)
+ procInfo.mFlags |= flags[i];
+ }
+
+ procInfo.mTimeoutMS = aTimeoutMS;
+
+ if (aAffinity)
+ {
+ com::SafeArray<LONG> affinity(ComSafeArrayInArg(aAffinity));
+ for (size_t i = 0; i < affinity.size(); i++)
+ procInfo.mAffinity[i] = affinity[i]; /** @todo Really necessary? Later. */
+ }
+
+ procInfo.mPriority = aPriority;
+
+ ComObjPtr<GuestProcess> pProcess;
+ rc = processCreateExInteral(procInfo, pProcess);
+ if (RT_SUCCESS(rc))
+ {
+ /* Return guest session to the caller. */
+ HRESULT hr2 = pProcess.queryInterfaceTo(aProcess);
+ if (FAILED(hr2))
+ rc = VERR_COM_OBJECT_NOT_FOUND;
+
+ if (RT_SUCCESS(rc))
+ rc = pProcess->startProcessAsync();
+ }
+ }
+
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_MAX_PROCS_REACHED:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest objects per session (%ld) reached"),
+ VBOX_GUESTCTRL_MAX_OBJECTS);
+ break;
+
+ /** @todo Add more errors here. */
+
+ default:
+ hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest process, rc=%Rrc"), rc);
+ break;
+ }
+ }
+
+ LogFlowFuncLeaveRC(rc);
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::ProcessGet(ULONG aPID, IGuestProcess **aProcess)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFunc(("aPID=%RU32\n", aPID));
+
+ CheckComArgOutPointerValid(aProcess);
+ if (aPID == 0)
+ return setError(E_INVALIDARG, tr("No valid process ID (PID) specified"));
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ HRESULT hr = S_OK;
+
+ ComObjPtr<GuestProcess> pProcess;
+ int rc = processGetByPID(aPID, &pProcess);
+ if (RT_FAILURE(rc))
+ hr = setError(E_INVALIDARG, tr("No process with PID %RU32 found"), aPID);
+
+ /* This will set (*aProcess) to NULL if pProgress is NULL. */
+ HRESULT hr2 = pProcess.queryInterfaceTo(aProcess);
+ if (SUCCEEDED(hr))
+ hr = hr2;
+
+ LogFlowThisFunc(("aProcess=%p, hr=%Rhrc\n", *aProcess, hr));
+ return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::SymlinkCreate(IN_BSTR aSource, IN_BSTR aTarget, SymlinkType_T aType)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::SymlinkExists(IN_BSTR aSymlink, BOOL *aExists)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::SymlinkRead(IN_BSTR aSymlink, ComSafeArrayIn(SymlinkReadFlag_T, aFlags), BSTR *aTarget)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::SymlinkRemoveDirectory(IN_BSTR aPath)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestSession::SymlinkRemoveFile(IN_BSTR aFile)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+ ReturnComNotImplemented();
+#else
+ LogFlowThisFuncEnter();
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ ReturnComNotImplemented();
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
diff --git a/src/VBox/Main/src-client/GuestSessionImplTasks.cpp b/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
new file mode 100644
index 000000000..84866b30f
--- /dev/null
+++ b/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
@@ -0,0 +1,1423 @@
+
+/* $Id: GuestSessionImplTasks.cpp $ */
+/** @file
+ * VirtualBox Main - XXX.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "GuestImpl.h"
+#include "GuestSessionImpl.h"
+#include "GuestCtrlImplPrivate.h"
+
+#include "Global.h"
+#include "AutoCaller.h"
+#include "ConsoleImpl.h"
+#include "MachineImpl.h"
+#include "ProgressImpl.h"
+
+#include <memory> /* For auto_ptr. */
+
+#include <iprt/env.h>
+#include <iprt/file.h> /* For CopyTo/From. */
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
+#include <VBox/log.h>
+
+
+/*******************************************************************************
+* Defines *
+*******************************************************************************/
+
+/**
+ * Update file flags.
+ */
+#define UPDATEFILE_FLAG_NONE 0
+/** Copy over the file from host to the
+ * guest. */
+#define UPDATEFILE_FLAG_COPY_FROM_ISO RT_BIT(0)
+/** Execute file on the guest after it has
+ * been successfully transfered. */
+#define UPDATEFILE_FLAG_EXECUTE RT_BIT(7)
+/** File is optional, does not have to be
+ * existent on the .ISO. */
+#define UPDATEFILE_FLAG_OPTIONAL RT_BIT(8)
+
+
+// session task classes
+/////////////////////////////////////////////////////////////////////////////
+
+GuestSessionTask::GuestSessionTask(GuestSession *pSession)
+{
+ mSession = pSession;
+}
+
+GuestSessionTask::~GuestSessionTask(void)
+{
+}
+
+int GuestSessionTask::getGuestProperty(const ComObjPtr<Guest> &pGuest,
+ const Utf8Str &strPath, Utf8Str &strValue)
+{
+ ComObjPtr<Console> pConsole = pGuest->getConsole();
+ const ComPtr<IMachine> pMachine = pConsole->machine();
+
+ Assert(!pMachine.isNull());
+ Bstr strTemp, strFlags;
+ LONG64 i64Timestamp;
+ HRESULT hr = pMachine->GetGuestProperty(Bstr(strPath).raw(),
+ strTemp.asOutParam(),
+ &i64Timestamp, strFlags.asOutParam());
+ if (SUCCEEDED(hr))
+ {
+ strValue = strTemp;
+ return VINF_SUCCESS;
+ }
+ return VERR_NOT_FOUND;
+}
+
+int GuestSessionTask::setProgress(ULONG uPercent)
+{
+ if (mProgress.isNull()) /* Progress is optional. */
+ return VINF_SUCCESS;
+
+ BOOL fCanceled;
+ if ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
+ && fCanceled)
+ return VERR_CANCELLED;
+ BOOL fCompleted;
+ if ( SUCCEEDED(mProgress->COMGETTER(Completed(&fCompleted)))
+ && fCompleted)
+ {
+ AssertMsgFailed(("Setting value of an already completed progress\n"));
+ return VINF_SUCCESS;
+ }
+ HRESULT hr = mProgress->SetCurrentOperationProgress(uPercent);
+ if (FAILED(hr))
+ return VERR_COM_UNEXPECTED;
+
+ return VINF_SUCCESS;
+}
+
+int GuestSessionTask::setProgressSuccess(void)
+{
+ if (mProgress.isNull()) /* Progress is optional. */
+ return VINF_SUCCESS;
+
+ BOOL fCanceled;
+ BOOL fCompleted;
+ if ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
+ && !fCanceled
+ && SUCCEEDED(mProgress->COMGETTER(Completed(&fCompleted)))
+ && !fCompleted)
+ {
+ HRESULT hr = mProgress->notifyComplete(S_OK);
+ if (FAILED(hr))
+ return VERR_COM_UNEXPECTED; /** @todo Find a better rc. */
+ }
+
+ return VINF_SUCCESS;
+}
+
+HRESULT GuestSessionTask::setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg)
+{
+ if (mProgress.isNull()) /* Progress is optional. */
+ return hr; /* Return original rc. */
+
+ BOOL fCanceled;
+ BOOL fCompleted;
+ if ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
+ && !fCanceled
+ && SUCCEEDED(mProgress->COMGETTER(Completed(&fCompleted)))
+ && !fCompleted)
+ {
+ HRESULT hr2 = mProgress->notifyComplete(hr,
+ COM_IIDOF(IGuestSession),
+ GuestSession::getStaticComponentName(),
+ strMsg.c_str());
+ if (FAILED(hr2))
+ return hr2;
+ }
+ return hr; /* Return original rc. */
+}
+
+SessionTaskCopyTo::SessionTaskCopyTo(GuestSession *pSession,
+ const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags)
+ : GuestSessionTask(pSession),
+ mSource(strSource),
+ mSourceFile(NULL),
+ mSourceOffset(0),
+ mSourceSize(0),
+ mDest(strDest)
+{
+ mCopyFileFlags = uFlags;
+}
+
+/** @todo Merge this and the above call and let the above call do the open/close file handling so that the
+ * inner code only has to deal with file handles. No time now ... */
+SessionTaskCopyTo::SessionTaskCopyTo(GuestSession *pSession,
+ PRTFILE pSourceFile, size_t cbSourceOffset, uint64_t cbSourceSize,
+ const Utf8Str &strDest, uint32_t uFlags)
+ : GuestSessionTask(pSession)
+{
+ mSourceFile = pSourceFile;
+ mSourceOffset = cbSourceOffset;
+ mSourceSize = cbSourceSize;
+ mDest = strDest;
+ mCopyFileFlags = uFlags;
+}
+
+SessionTaskCopyTo::~SessionTaskCopyTo(void)
+{
+
+}
+
+int SessionTaskCopyTo::Run(void)
+{
+ LogFlowThisFuncEnter();
+
+ ComObjPtr<GuestSession> pSession = mSession;
+ Assert(!pSession.isNull());
+
+ AutoCaller autoCaller(pSession);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ if (mCopyFileFlags)
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Copy flags (%#x) not implemented yet"),
+ mCopyFileFlags));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ int rc;
+
+ RTFILE fileLocal;
+ PRTFILE pFile = &fileLocal;
+
+ if (!mSourceFile)
+ {
+ /* Does our source file exist? */
+ if (!RTFileExists(mSource.c_str()))
+ {
+ rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Source file \"%s\" does not exist or is not a file"),
+ mSource.c_str()));
+ }
+ else
+ {
+ rc = RTFileOpen(pFile, mSource.c_str(),
+ RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
+ if (RT_FAILURE(rc))
+ {
+ rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Could not open source file \"%s\" for reading: %Rrc"),
+ mSource.c_str(), rc));
+ }
+ else
+ {
+ rc = RTFileGetSize(*pFile, &mSourceSize);
+ if (RT_FAILURE(rc))
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Could not query file size of \"%s\": %Rrc"),
+ mSource.c_str(), rc));
+ }
+ }
+ }
+ }
+ else
+ {
+ pFile = mSourceFile;
+ /* Size + offset are optional. */
+ }
+
+ GuestProcessStartupInfo procInfo;
+ procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT);
+ procInfo.mFlags = ProcessCreateFlag_Hidden;
+
+ /* Set arguments.*/
+ procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", mDest.c_str())); /** @todo Do we need path conversion? */
+
+ /* Startup process. */
+ ComObjPtr<GuestProcess> pProcess; int guestRc;
+ rc = pSession->processCreateExInteral(procInfo, pProcess);
+ if (RT_SUCCESS(rc))
+ rc = pProcess->startProcess(&guestRc);
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
+ break;
+
+ default:
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
+ mSource.c_str(), rc));
+ break;
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ ProcessWaitResult_T waitRes;
+ BYTE byBuf[_64K];
+
+ BOOL fCanceled = FALSE;
+ uint64_t cbWrittenTotal = 0;
+ uint64_t cbToRead = mSourceSize;
+
+ for (;;)
+ {
+ rc = pProcess->waitFor(ProcessWaitForFlag_StdIn,
+ 30 * 1000 /* Timeout */, waitRes, &guestRc);
+ if ( RT_FAILURE(rc)
+ || ( waitRes != ProcessWaitResult_StdIn
+ && waitRes != ProcessWaitResult_WaitFlagNotSupported))
+ {
+ break;
+ }
+
+ /* If the guest does not support waiting for stdin, we now yield in
+ * order to reduce the CPU load due to busy waiting. */
+ if (waitRes == ProcessWaitResult_WaitFlagNotSupported)
+ RTThreadSleep(1); /* Optional, don't check rc. */
+
+ size_t cbRead = 0;
+ if (mSourceSize) /* If we have nothing to write, take a shortcut. */
+ {
+ /** @todo Not very efficient, but works for now. */
+ rc = RTFileSeek(*pFile, mSourceOffset + cbWrittenTotal,
+ RTFILE_SEEK_BEGIN, NULL /* poffActual */);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTFileRead(*pFile, (uint8_t*)byBuf,
+ RT_MIN(cbToRead, sizeof(byBuf)), &cbRead);
+ /*
+ * Some other error occured? There might be a chance that RTFileRead
+ * could not resolve/map the native error code to an IPRT code, so just
+ * print a generic error.
+ */
+ if (RT_FAILURE(rc))
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"),
+ mSource.c_str(), rc));
+ break;
+ }
+ }
+ else
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" to offset %RU64 failed: %Rrc"),
+ mSource.c_str(), cbWrittenTotal, rc));
+ break;
+ }
+ }
+
+ uint32_t fFlags = ProcessInputFlag_None;
+
+ /* Did we reach the end of the content we want to transfer (last chunk)? */
+ if ( (cbRead < sizeof(byBuf))
+ /* Did we reach the last block which is exactly _64K? */
+ || (cbToRead - cbRead == 0)
+ /* ... or does the user want to cancel? */
+ || ( !mProgress.isNull()
+ && SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
+ && fCanceled)
+ )
+ {
+ LogFlowThisFunc(("Writing last chunk cbRead=%RU64\n", cbRead));
+ fFlags |= ProcessInputFlag_EndOfFile;
+ }
+
+ uint32_t cbWritten;
+ Assert(sizeof(byBuf) >= cbRead);
+ rc = pProcess->writeData(0 /* StdIn */, fFlags,
+ byBuf, cbRead,
+ 30 * 1000 /* Timeout */, &cbWritten, &guestRc);
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
+ break;
+
+ default:
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"),
+ mDest.c_str(), cbWrittenTotal, rc));
+ break;
+ }
+
+ break;
+ }
+
+ /* Only subtract bytes reported written by the guest. */
+ Assert(cbToRead >= cbWritten);
+ cbToRead -= cbWritten;
+
+ /* Update total bytes written to the guest. */
+ cbWrittenTotal += cbWritten;
+ Assert(cbWrittenTotal <= mSourceSize);
+
+ LogFlowThisFunc(("rc=%Rrc, cbWritten=%RU32, cbToRead=%RU64, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
+ rc, cbWritten, cbToRead, cbWrittenTotal, mSourceSize));
+
+ /* Did the user cancel the operation above? */
+ if (fCanceled)
+ break;
+
+ /* Update the progress.
+ * Watch out for division by zero. */
+ mSourceSize > 0
+ ? rc = setProgress((ULONG)(cbWrittenTotal * 100 / mSourceSize))
+ : rc = setProgress(100);
+ if (RT_FAILURE(rc))
+ break;
+
+ /* End of file reached? */
+ if (!cbToRead)
+ break;
+ } /* for */
+
+ LogFlowThisFunc(("Copy loop ended with rc=%Rrc\n" ,rc));
+
+ if ( !fCanceled
+ || RT_SUCCESS(rc))
+ {
+ /*
+ * Even if we succeeded until here make sure to check whether we really transfered
+ * everything.
+ */
+ if ( mSourceSize > 0
+ && cbWrittenTotal == 0)
+ {
+ /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
+ * to the destination -> access denied. */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
+ mSource.c_str(), mDest.c_str()));
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ else if (cbWrittenTotal < mSourceSize)
+ {
+ /* If we did not copy all let the user know. */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"),
+ mSource.c_str(), cbWrittenTotal, mSourceSize));
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ else
+ {
+ rc = pProcess->waitFor(ProcessWaitForFlag_Terminate,
+ 30 * 1000 /* Timeout */, waitRes, &guestRc);
+ if ( RT_FAILURE(rc)
+ || waitRes != ProcessWaitResult_Terminate)
+ {
+ if (RT_FAILURE(rc))
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed: %Rrc"),
+ mSource.c_str(), rc));
+ else
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Waiting on termination for copying file \"%s\" failed with wait result %ld"),
+ mSource.c_str(), waitRes));
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ ProcessStatus_T procStatus;
+ LONG exitCode;
+ if ( ( SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
+ && procStatus != ProcessStatus_TerminatedNormally)
+ || ( SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
+ && exitCode != 0)
+ )
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %ld"),
+ mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ rc = setProgressSuccess();
+ }
+ }
+
+ if (!pProcess.isNull())
+ pProcess->uninit();
+ } /* processCreateExInteral */
+
+ if (!mSourceFile) /* Only close locally opened files. */
+ RTFileClose(*pFile);
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+int SessionTaskCopyTo::RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress)
+{
+ LogFlowThisFunc(("strDesc=%s, strSource=%s, strDest=%s, mCopyFileFlags=%x\n",
+ strDesc.c_str(), mSource.c_str(), mDest.c_str(), mCopyFileFlags));
+
+ mDesc = strDesc;
+ mProgress = pProgress;
+
+ int rc = RTThreadCreate(NULL, SessionTaskCopyTo::taskThread, this,
+ 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
+ "gctlCpyTo");
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+/* static */
+int SessionTaskCopyTo::taskThread(RTTHREAD Thread, void *pvUser)
+{
+ std::auto_ptr<SessionTaskCopyTo> task(static_cast<SessionTaskCopyTo*>(pvUser));
+ AssertReturn(task.get(), VERR_GENERAL_FAILURE);
+
+ LogFlowFunc(("pTask=%p\n", task.get()));
+ return task->Run();
+}
+
+SessionTaskCopyFrom::SessionTaskCopyFrom(GuestSession *pSession,
+ const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags)
+ : GuestSessionTask(pSession)
+{
+ mSource = strSource;
+ mDest = strDest;
+ mFlags = uFlags;
+}
+
+SessionTaskCopyFrom::~SessionTaskCopyFrom(void)
+{
+
+}
+
+int SessionTaskCopyFrom::Run(void)
+{
+ LogFlowThisFuncEnter();
+
+ ComObjPtr<GuestSession> pSession = mSession;
+ Assert(!pSession.isNull());
+
+ AutoCaller autoCaller(pSession);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /*
+ * Note: There will be races between querying file size + reading the guest file's
+ * content because we currently *do not* lock down the guest file when doing the
+ * actual operations.
+ ** @todo Implement guest file locking!
+ */
+ GuestFsObjData objData; int guestRc;
+ int rc = pSession->fileQueryInfoInternal(Utf8Str(mSource), objData, &guestRc);
+ if (RT_FAILURE(rc))
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Querying guest file information for \"%s\" failed: %Rrc"),
+ mSource.c_str(), rc));
+ }
+ else if (objData.mType != FsObjType_File) /* Only single files are supported at the moment. */
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Object \"%s\" on the guest is not a file"), mSource.c_str()));
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ RTFILE fileDest;
+ rc = RTFileOpen(&fileDest, mDest.c_str(),
+ RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */
+ if (RT_FAILURE(rc))
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error opening destination file \"%s\": %Rrc"),
+ mDest.c_str(), rc));
+ }
+ else
+ {
+ GuestProcessStartupInfo procInfo;
+ procInfo.mName = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
+ mSource.c_str(), mDest.c_str(), objData.mObjectSize);
+ procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT);
+ procInfo.mFlags = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
+
+ /* Set arguments.*/
+ procInfo.mArguments.push_back(mSource); /* Which file to output? */
+
+ /* Startup process. */
+ ComObjPtr<GuestProcess> pProcess;
+ rc = pSession->processCreateExInteral(procInfo, pProcess);
+ if (RT_SUCCESS(rc))
+ rc = pProcess->startProcess(&guestRc);
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
+ break;
+
+ default:
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
+ mSource.c_str(), rc));
+ break;
+ }
+ }
+ else
+ {
+ ProcessWaitResult_T waitRes;
+ BYTE byBuf[_64K];
+
+ BOOL fCanceled = FALSE;
+ uint64_t cbWrittenTotal = 0;
+ uint64_t cbToRead = objData.mObjectSize;
+
+ for (;;)
+ {
+ rc = pProcess->waitFor(ProcessWaitForFlag_StdOut,
+ 30 * 1000 /* Timeout */, waitRes, &guestRc);
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
+ break;
+
+ default:
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error while creating guest process for copying file \"%s\" from guest to host: %Rrc"),
+ mSource.c_str(), rc));
+ break;
+ }
+
+ break;
+ }
+
+ if ( waitRes == ProcessWaitResult_StdOut
+ || waitRes == ProcessWaitResult_WaitFlagNotSupported)
+ {
+ /* If the guest does not support waiting for stdin, we now yield in
+ * order to reduce the CPU load due to busy waiting. */
+ if (waitRes == ProcessWaitResult_WaitFlagNotSupported)
+ RTThreadSleep(1); /* Optional, don't check rc. */
+
+ size_t cbRead;
+ rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
+ 30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
+ &cbRead, &guestRc);
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
+ break;
+
+ default:
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Reading from file \"%s\" (offset %RU64) failed: %Rrc"),
+ mSource.c_str(), cbWrittenTotal, rc));
+ break;
+ }
+
+ break;
+ }
+
+ if (cbRead)
+ {
+ rc = RTFileWrite(fileDest, byBuf, cbRead, NULL /* No partial writes */);
+ if (RT_FAILURE(rc))
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error writing to file \"%s\" (%RU64 bytes left): %Rrc"),
+ mDest.c_str(), cbToRead, rc));
+ break;
+ }
+
+ /* Only subtract bytes reported written by the guest. */
+ Assert(cbToRead >= cbRead);
+ cbToRead -= cbRead;
+
+ /* Update total bytes written to the guest. */
+ cbWrittenTotal += cbRead;
+ Assert(cbWrittenTotal <= (uint64_t)objData.mObjectSize);
+
+ /* Did the user cancel the operation above? */
+ if ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled)))
+ && fCanceled)
+ break;
+
+ rc = setProgress((ULONG)(cbWrittenTotal / ((uint64_t)objData.mObjectSize / 100.0)));
+ if (RT_FAILURE(rc))
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ } /* for */
+
+ LogFlowThisFunc(("rc=%Rrc, guestrc=%Rrc, waitRes=%ld, cbWrittenTotal=%RU64, cbSize=%RI64, cbToRead=%RU64\n",
+ rc, guestRc, waitRes, cbWrittenTotal, objData.mObjectSize, cbToRead));
+
+ if ( !fCanceled
+ || RT_SUCCESS(rc))
+ {
+ /*
+ * Even if we succeeded until here make sure to check whether we really transfered
+ * everything.
+ */
+ if ( objData.mObjectSize > 0
+ && cbWrittenTotal == 0)
+ {
+ /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
+ * to the destination -> access denied. */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""),
+ mSource.c_str(), mDest.c_str()));
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ else if (cbWrittenTotal < (uint64_t)objData.mObjectSize)
+ {
+ /* If we did not copy all let the user know. */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RI64 bytes transfered)"),
+ mSource.c_str(), cbWrittenTotal, objData.mObjectSize));
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ else
+ {
+ ProcessStatus_T procStatus;
+ LONG exitCode;
+ if ( ( SUCCEEDED(pProcess->COMGETTER(Status(&procStatus)))
+ && procStatus != ProcessStatus_TerminatedNormally)
+ || ( SUCCEEDED(pProcess->COMGETTER(ExitCode(&exitCode)))
+ && exitCode != 0)
+ )
+ {
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed with status %ld, exit code %d"),
+ mSource.c_str(), procStatus, exitCode)); /**@todo Add stringify methods! */
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ else /* Yay, success! */
+ rc = setProgressSuccess();
+ }
+ }
+
+ if (!pProcess.isNull())
+ pProcess->uninit();
+ }
+
+ RTFileClose(fileDest);
+ }
+ }
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+int SessionTaskCopyFrom::RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress)
+{
+ LogFlowThisFunc(("strDesc=%s, strSource=%s, strDest=%s, uFlags=%x\n",
+ strDesc.c_str(), mSource.c_str(), mDest.c_str(), mFlags));
+
+ mDesc = strDesc;
+ mProgress = pProgress;
+
+ int rc = RTThreadCreate(NULL, SessionTaskCopyFrom::taskThread, this,
+ 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
+ "gctlCpyFrom");
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+/* static */
+int SessionTaskCopyFrom::taskThread(RTTHREAD Thread, void *pvUser)
+{
+ std::auto_ptr<SessionTaskCopyFrom> task(static_cast<SessionTaskCopyFrom*>(pvUser));
+ AssertReturn(task.get(), VERR_GENERAL_FAILURE);
+
+ LogFlowFunc(("pTask=%p\n", task.get()));
+ return task->Run();
+}
+
+SessionTaskUpdateAdditions::SessionTaskUpdateAdditions(GuestSession *pSession,
+ const Utf8Str &strSource, uint32_t uFlags)
+ : GuestSessionTask(pSession)
+{
+ mSource = strSource;
+ mFlags = uFlags;
+}
+
+SessionTaskUpdateAdditions::~SessionTaskUpdateAdditions(void)
+{
+
+}
+
+int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,
+ Utf8Str const &strFileSource, const Utf8Str &strFileDest,
+ bool fOptional, uint32_t *pcbSize)
+{
+ AssertPtrReturn(pSession, VERR_INVALID_POINTER);
+ AssertPtrReturn(pISO, VERR_INVALID_POINTER);
+ /* pcbSize is optional. */
+
+ uint32_t cbOffset;
+ size_t cbSize;
+
+ int rc = RTIsoFsGetFileInfo(pISO, strFileSource.c_str(), &cbOffset, &cbSize);
+ if (RT_FAILURE(rc))
+ {
+ if (fOptional)
+ return VINF_SUCCESS;
+
+ return rc;
+ }
+
+ Assert(cbOffset);
+ Assert(cbSize);
+ rc = RTFileSeek(pISO->file, cbOffset, RTFILE_SEEK_BEGIN, NULL);
+
+ /* Copy over the Guest Additions file to the guest. */
+ if (RT_SUCCESS(rc))
+ {
+ LogFlowThisFunc(("Copying Guest Additions installer file \"%s\" to \"%s\" on guest ...\n",
+ strFileSource.c_str(), strFileDest.c_str()));
+
+ if (RT_SUCCESS(rc))
+ {
+ SessionTaskCopyTo *pTask = new SessionTaskCopyTo(pSession /* GuestSession */,
+ &pISO->file, cbOffset, cbSize,
+ strFileDest, CopyFileFlag_None);
+ AssertPtrReturn(pTask, VERR_NO_MEMORY);
+
+ ComObjPtr<Progress> pProgressCopyTo;
+ rc = pSession->startTaskAsync(Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer file \"%s\" to \"%s\" on guest"),
+ mSource.c_str(), strFileDest.c_str()),
+ pTask, pProgressCopyTo);
+ if (RT_SUCCESS(rc))
+ {
+ BOOL fCanceled = FALSE;
+ HRESULT hr = pProgressCopyTo->WaitForCompletion(-1);
+ if ( SUCCEEDED(pProgressCopyTo->COMGETTER(Canceled)(&fCanceled))
+ && fCanceled)
+ {
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ else if (FAILED(hr))
+ {
+ Assert(FAILED(hr));
+ rc = VERR_GENERAL_FAILURE; /* Fudge. */
+ }
+ }
+ }
+ }
+
+ /** @todo Note: Since there is no file locking involved at the moment, there can be modifications
+ * between finished copying, the verification and the actual execution. */
+
+ /* Determine where the installer image ended up and if it has the correct size. */
+ if (RT_SUCCESS(rc))
+ {
+ LogFlowThisFunc(("Verifying Guest Additions installer file \"%s\" ...\n",
+ strFileDest.c_str()));
+
+ GuestFsObjData objData;
+ int64_t cbSizeOnGuest; int guestRc;
+ rc = pSession->fileQuerySizeInternal(strFileDest, &cbSizeOnGuest, &guestRc);
+ if ( RT_SUCCESS(rc)
+ && cbSize == (uint64_t)cbSizeOnGuest)
+ {
+ LogFlowThisFunc(("Guest Additions installer file \"%s\" successfully verified\n",
+ strFileDest.c_str()));
+ }
+ else
+ {
+ if (RT_SUCCESS(rc)) /* Size does not match. */
+ {
+ LogFlowThisFunc(("Size of Guest Additions installer file \"%s\" does not match: %RI64bytes copied, %RU64bytes expected\n",
+ strFileDest.c_str(), cbSizeOnGuest, cbSize));
+ rc = VERR_BROKEN_PIPE; /** @todo Find a better error. */
+ }
+ else
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
+ break;
+
+ default:
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error while querying size for file \"%s\": %Rrc"),
+ strFileDest.c_str(), rc));
+ break;
+ }
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ if (pcbSize)
+ *pcbSize = cbSizeOnGuest;
+ }
+ }
+
+ return rc;
+}
+
+int SessionTaskUpdateAdditions::runFileOnGuest(GuestSession *pSession, GuestProcessStartupInfo &procInfo)
+{
+ AssertPtrReturn(pSession, VERR_INVALID_POINTER);
+
+ LogRel(("Running %s ...\n", procInfo.mName.c_str()));
+
+ LONG exitCode;
+ GuestProcessTool procTool; int guestRc;
+ int vrc = procTool.Init(pSession, procInfo, false /* Async */, &guestRc);
+ if (RT_SUCCESS(vrc))
+ {
+ if (RT_SUCCESS(guestRc))
+ vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
+ if (RT_SUCCESS(vrc))
+ vrc = procTool.TerminatedOk(&exitCode);
+ }
+
+ if (RT_FAILURE(vrc))
+ {
+ switch (vrc)
+ {
+ case VERR_NOT_EQUAL: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Running update file \"%s\" on guest terminated with exit code %ld"),
+ procInfo.mCommand.c_str(), exitCode));
+ break;
+
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
+ break;
+
+ case VERR_INVALID_STATE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Update file \"%s\" reported invalid running state"),
+ procInfo.mCommand.c_str()));
+ break;
+
+ default:
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error while running update file \"%s\" on guest: %Rrc"),
+ procInfo.mCommand.c_str(), vrc));
+ break;
+ }
+ }
+
+ return vrc;
+}
+
+int SessionTaskUpdateAdditions::Run(void)
+{
+ LogFlowThisFuncEnter();
+
+ ComObjPtr<GuestSession> pSession = mSession;
+ Assert(!pSession.isNull());
+
+ AutoCaller autoCaller(pSession);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ int rc = setProgress(10);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ HRESULT hr = S_OK;
+
+ LogRel(("Automatic update of Guest Additions started, using \"%s\"\n", mSource.c_str()));
+
+ ComObjPtr<Guest> pGuest(mSession->getParent());
+#if 0
+ /*
+ * Wait for the guest being ready within 30 seconds.
+ */
+ AdditionsRunLevelType_T addsRunLevel;
+ uint64_t tsStart = RTTimeSystemMilliTS();
+ while ( SUCCEEDED(hr = pGuest->COMGETTER(AdditionsRunLevel)(&addsRunLevel))
+ && ( addsRunLevel != AdditionsRunLevelType_Userland
+ && addsRunLevel != AdditionsRunLevelType_Desktop))
+ {
+ if ((RTTimeSystemMilliTS() - tsStart) > 30 * 1000)
+ {
+ rc = VERR_TIMEOUT;
+ break;
+ }
+
+ RTThreadSleep(100); /* Wait a bit. */
+ }
+
+ if (FAILED(hr)) rc = VERR_TIMEOUT;
+ if (rc == VERR_TIMEOUT)
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("Guest Additions were not ready within time, giving up")));
+#else
+ /*
+ * For use with the GUI we don't want to wait, just return so that the manual .ISO mounting
+ * can continue.
+ */
+ AdditionsRunLevelType_T addsRunLevel;
+ if ( FAILED(hr = pGuest->COMGETTER(AdditionsRunLevel)(&addsRunLevel))
+ || ( addsRunLevel != AdditionsRunLevelType_Userland
+ && addsRunLevel != AdditionsRunLevelType_Desktop))
+ {
+ if (addsRunLevel == AdditionsRunLevelType_System)
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("Guest Additions are installed but not fully loaded yet, aborting automatic update")));
+ else
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("Guest Additions not installed or ready, aborting automatic update")));
+ rc = VERR_NOT_SUPPORTED;
+ }
+#endif
+
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Determine if we are able to update automatically. This only works
+ * if there are recent Guest Additions installed already.
+ */
+ Utf8Str strAddsVer;
+ rc = getGuestProperty(pGuest, "/VirtualBox/GuestAdd/Version", strAddsVer);
+ if ( RT_SUCCESS(rc)
+ && RTStrVersionCompare(strAddsVer.c_str(), "4.1") < 0)
+ {
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("Guest has too old Guest Additions (%s) installed for automatic updating, please update manually"),
+ strAddsVer.c_str()));
+ rc = VERR_NOT_SUPPORTED;
+ }
+ }
+
+ Utf8Str strOSVer;
+ eOSType osType;
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Determine guest OS type and the required installer image.
+ */
+ Utf8Str strOSType;
+ rc = getGuestProperty(pGuest, "/VirtualBox/GuestInfo/OS/Product", strOSType);
+ if (RT_SUCCESS(rc))
+ {
+ if ( strOSType.contains("Microsoft", Utf8Str::CaseInsensitive)
+ || strOSType.contains("Windows", Utf8Str::CaseInsensitive))
+ {
+ osType = eOSType_Windows;
+
+ /*
+ * Determine guest OS version.
+ */
+ rc = getGuestProperty(pGuest, "/VirtualBox/GuestInfo/OS/Release", strOSVer);
+ if (RT_FAILURE(rc))
+ {
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("Unable to detected guest OS version, please update manually")));
+ rc = VERR_NOT_SUPPORTED;
+ }
+
+ /* Because Windows 2000 + XP and is bitching with WHQL popups even if we have signed drivers we
+ * can't do automated updates here. */
+ /* Windows XP 64-bit (5.2) is a Windows 2003 Server actually, so skip this here. */
+ if ( RT_SUCCESS(rc)
+ && ( strOSVer.startsWith("5.0") /* Exclude the build number. */
+ || strOSVer.startsWith("5.1")) /* Exclude the build number. */
+ )
+ {
+ /* If we don't have AdditionsUpdateFlag_WaitForUpdateStartOnly set we can't continue
+ * because the Windows Guest Additions installer will fail because of WHQL popups. If the
+ * flag is set this update routine ends successfully as soon as the installer was started
+ * (and the user has to deal with it in the guest). */
+ if (!(mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly))
+ {
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("Windows 2000 and XP are not supported for automatic updating due to WHQL interaction, please update manually")));
+ rc = VERR_NOT_SUPPORTED;
+ }
+ }
+ }
+ else if (strOSType.contains("Solaris", Utf8Str::CaseInsensitive))
+ {
+ osType = eOSType_Solaris;
+ }
+ else /* Everything else hopefully means Linux :-). */
+ osType = eOSType_Linux;
+
+#if 1 /* Only Windows is supported (and tested) at the moment. */
+ if (osType != eOSType_Windows)
+ {
+ hr = setProgressErrorMsg(VBOX_E_NOT_SUPPORTED,
+ Utf8StrFmt(GuestSession::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"),
+ strOSType.c_str()));
+ rc = VERR_NOT_SUPPORTED;
+ }
+#endif
+ }
+ }
+
+ RTISOFSFILE iso;
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Try to open the .ISO file to extract all needed files.
+ */
+ rc = RTIsoFsOpen(&iso, mSource.c_str());
+ if (RT_FAILURE(rc))
+ {
+ hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Unable to open Guest Additions .ISO file \"%s\": %Rrc"),
+ mSource.c_str(), rc));
+ }
+ else
+ {
+ /* Set default installation directories. */
+ Utf8Str strUpdateDir = "/tmp/";
+ if (osType == eOSType_Windows)
+ strUpdateDir = "C:\\Temp\\";
+
+ rc = setProgress(5);
+
+ /* Try looking up the Guest Additions installation directory. */
+ if (RT_SUCCESS(rc))
+ {
+ /* Try getting the installed Guest Additions version to know whether we
+ * can install our temporary Guest Addition data into the original installation
+ * directory.
+ *
+ * Because versions prior to 4.2 had bugs wrt spaces in paths we have to choose
+ * a different location then.
+ */
+ bool fUseInstallDir = false;
+
+ Utf8Str strAddsVer;
+ rc = getGuestProperty(pGuest, "/VirtualBox/GuestAdd/Version", strAddsVer);
+ if ( RT_SUCCESS(rc)
+ && RTStrVersionCompare(strAddsVer.c_str(), "4.2r80329") > 0)
+ {
+ fUseInstallDir = true;
+ }
+
+ if (fUseInstallDir)
+ {
+ if (RT_SUCCESS(rc))
+ rc = getGuestProperty(pGuest, "/VirtualBox/GuestAdd/InstallDir", strUpdateDir);
+ if (RT_SUCCESS(rc))
+ {
+ if (osType == eOSType_Windows)
+ {
+ strUpdateDir.findReplace('/', '\\');
+ strUpdateDir.append("\\Update\\");
+ }
+ else
+ strUpdateDir.append("/update/");
+ }
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ LogRel(("Guest Additions update directory is: %s\n",
+ strUpdateDir.c_str()));
+
+ /* Create the installation directory. */
+ int guestRc;
+ rc = pSession->directoryCreateInternal(strUpdateDir,
+ 755 /* Mode */, DirectoryCreateFlag_Parents, &guestRc);
+ if (RT_FAILURE(rc))
+ {
+ switch (rc)
+ {
+ case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ GuestProcess::guestErrorToString(guestRc));
+ break;
+
+ default:
+ setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error creating installation directory \"%s\" on the guest: %Rrc"),
+ strUpdateDir.c_str(), rc));
+ break;
+ }
+ }
+ if (RT_SUCCESS(rc))
+ rc = setProgress(10);
+
+ if (RT_SUCCESS(rc))
+ {
+ /* Prepare the file(s) we want to copy over to the guest and
+ * (maybe) want to run. */
+ switch (osType)
+ {
+ case eOSType_Windows:
+ {
+ /* Do we need to install our certificates? We do this for W2K and up. */
+ bool fInstallCert = false;
+
+ /* Only Windows 2000 and up need certificates to be installed. */
+ if (RTStrVersionCompare(strOSVer.c_str(), "5.0") >= 0)
+ {
+ fInstallCert = true;
+ LogRel(("Certificates for auto updating WHQL drivers will be installed\n"));
+ }
+ else
+ LogRel(("Skipping installation of certificates for WHQL drivers\n"));
+
+ if (fInstallCert)
+ {
+ /* Our certificate. */
+ mFiles.push_back(InstallerFile("CERT/ORACLE_VBOX.CER",
+ strUpdateDir + "oracle-vbox.cer",
+ UPDATEFILE_FLAG_COPY_FROM_ISO | UPDATEFILE_FLAG_OPTIONAL));
+ /* Our certificate installation utility. */
+ /* First pass: Copy over the file + execute it to remove any existing
+ * VBox certificates. */
+ GuestProcessStartupInfo siCertUtilRem;
+ siCertUtilRem.mName = "VirtualBox Certificate Utility, removing old VirtualBox certificates";
+ siCertUtilRem.mArguments.push_back(Utf8Str("remove-trusted-publisher"));
+ siCertUtilRem.mArguments.push_back(Utf8Str("--root")); /* Add root certificate as well. */
+ siCertUtilRem.mArguments.push_back(Utf8Str(strUpdateDir + "oracle-vbox.cer"));
+ siCertUtilRem.mArguments.push_back(Utf8Str(strUpdateDir + "oracle-vbox.cer"));
+ mFiles.push_back(InstallerFile("CERT/VBOXCERTUTIL.EXE",
+ strUpdateDir + "VBoxCertUtil.exe",
+ UPDATEFILE_FLAG_COPY_FROM_ISO | UPDATEFILE_FLAG_EXECUTE | UPDATEFILE_FLAG_OPTIONAL,
+ siCertUtilRem));
+ /* Second pass: Only execute (but don't copy) again, this time installng the
+ * recent certificates just copied over. */
+ GuestProcessStartupInfo siCertUtilAdd;
+ siCertUtilAdd.mName = "VirtualBox Certificate Utility, installing VirtualBox certificates";
+ siCertUtilAdd.mArguments.push_back(Utf8Str("add-trusted-publisher"));
+ siCertUtilAdd.mArguments.push_back(Utf8Str("--root")); /* Add root certificate as well. */
+ siCertUtilAdd.mArguments.push_back(Utf8Str(strUpdateDir + "oracle-vbox.cer"));
+ siCertUtilAdd.mArguments.push_back(Utf8Str(strUpdateDir + "oracle-vbox.cer"));
+ mFiles.push_back(InstallerFile("CERT/VBOXCERTUTIL.EXE",
+ strUpdateDir + "VBoxCertUtil.exe",
+ UPDATEFILE_FLAG_EXECUTE | UPDATEFILE_FLAG_OPTIONAL,
+ siCertUtilAdd));
+ }
+ /* The installers in different flavors, as we don't know (and can't assume)
+ * the guest's bitness. */
+ mFiles.push_back(InstallerFile("VBOXWINDOWSADDITIONS_X86.EXE",
+ strUpdateDir + "VBoxWindowsAdditions-x86.exe",
+ UPDATEFILE_FLAG_COPY_FROM_ISO));
+ mFiles.push_back(InstallerFile("VBOXWINDOWSADDITIONS_AMD64.EXE",
+ strUpdateDir + "VBoxWindowsAdditions-amd64.exe",
+ UPDATEFILE_FLAG_COPY_FROM_ISO));
+ /* The stub loader which decides which flavor to run. */
+ GuestProcessStartupInfo siInstaller;
+ siInstaller.mName = "VirtualBox Windows Guest Additions Installer";
+ /* Set a running timeout of 5 minutes -- the Windows Guest Additions
+ * setup can take quite a while, so be on the safe side. */
+ siInstaller.mTimeoutMS = 5 * 60 * 1000;
+ siInstaller.mArguments.push_back(Utf8Str("/S")); /* We want to install in silent mode. */
+ siInstaller.mArguments.push_back(Utf8Str("/l")); /* ... and logging enabled. */
+ /* Don't quit VBoxService during upgrade because it still is used for this
+ * piece of code we're in right now (that is, here!) ... */
+ siInstaller.mArguments.push_back(Utf8Str("/no_vboxservice_exit"));
+ /* Tell the installer to report its current installation status
+ * using a running VBoxTray instance via balloon messages in the
+ * Windows taskbar. */
+ siInstaller.mArguments.push_back(Utf8Str("/post_installstatus"));
+ /* If the caller does not want to wait for out guest update process to end,
+ * complete the progress object now so that the caller can do other work. */
+ if (mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly)
+ siInstaller.mFlags |= ProcessCreateFlag_WaitForProcessStartOnly;
+ mFiles.push_back(InstallerFile("VBOXWINDOWSADDITIONS.EXE",
+ strUpdateDir + "VBoxWindowsAdditions.exe",
+ UPDATEFILE_FLAG_COPY_FROM_ISO | UPDATEFILE_FLAG_EXECUTE, siInstaller));
+ break;
+ }
+ case eOSType_Linux:
+ /** @todo Add Linux support. */
+ break;
+ case eOSType_Solaris:
+ /** @todo Add Solaris support. */
+ break;
+ default:
+ AssertReleaseMsgFailed(("Unsupported guest type: %d\n", osType));
+ break;
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ /* We want to spend 40% total for all copying operations. So roughly
+ * calculate the specific percentage step of each copied file. */
+ uint8_t uOffset = 20; /* Start at 20%. */
+ uint8_t uStep = 40 / mFiles.size();
+
+ LogRel(("Copying over Guest Additions update files to the guest ...\n"));
+
+ std::vector<InstallerFile>::const_iterator itFiles = mFiles.begin();
+ while (itFiles != mFiles.end())
+ {
+ if (itFiles->fFlags & UPDATEFILE_FLAG_COPY_FROM_ISO)
+ {
+ bool fOptional = false;
+ if (itFiles->fFlags & UPDATEFILE_FLAG_OPTIONAL)
+ fOptional = true;
+ rc = copyFileToGuest(pSession, &iso, itFiles->strSource, itFiles->strDest,
+ fOptional, NULL /* cbSize */);
+ if (RT_FAILURE(rc))
+ {
+ hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Error while copying file \"%s\" to \"%s\" on the guest: %Rrc"),
+ itFiles->strSource.c_str(), itFiles->strDest.c_str(), rc));
+ break;
+ }
+ }
+
+ rc = setProgress(uOffset);
+ if (RT_FAILURE(rc))
+ break;
+ uOffset += uStep;
+
+ itFiles++;
+ }
+ }
+
+ /* Done copying, close .ISO file. */
+ RTIsoFsClose(&iso);
+
+ if (RT_SUCCESS(rc))
+ {
+ /* We want to spend 35% total for all copying operations. So roughly
+ * calculate the specific percentage step of each copied file. */
+ uint8_t uOffset = 60; /* Start at 60%. */
+ uint8_t uStep = 35 / mFiles.size();
+
+ LogRel(("Executing Guest Additions update files ...\n"));
+
+ std::vector<InstallerFile>::iterator itFiles = mFiles.begin();
+ while (itFiles != mFiles.end())
+ {
+ if (itFiles->fFlags & UPDATEFILE_FLAG_EXECUTE)
+ {
+ rc = runFileOnGuest(pSession, itFiles->mProcInfo);
+ if (RT_FAILURE(rc))
+ break;
+ }
+
+ rc = setProgress(uOffset);
+ if (RT_FAILURE(rc))
+ break;
+ uOffset += uStep;
+
+ itFiles++;
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ LogRel(("Automatic update of Guest Additions succeeded\n"));
+ rc = setProgressSuccess();
+ }
+ }
+ }
+
+ if (RT_FAILURE(rc))
+ {
+ if (rc == VERR_CANCELLED)
+ {
+ LogRel(("Automatic update of Guest Additions was canceled\n"));
+
+ hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
+ Utf8StrFmt(GuestSession::tr("Installation was canceled")));
+ }
+ else
+ {
+ Utf8Str strError = Utf8StrFmt("No further error information available (%Rrc)", rc);
+ if (!mProgress.isNull()) /* Progress object is optional. */
+ {
+ ComPtr<IVirtualBoxErrorInfo> pError;
+ hr = mProgress->COMGETTER(ErrorInfo)(pError.asOutParam());
+ Assert(!pError.isNull());
+ if (SUCCEEDED(hr))
+ {
+ Bstr strVal;
+ hr = pError->COMGETTER(Text)(strVal.asOutParam());
+ if ( SUCCEEDED(hr)
+ && strVal.isNotEmpty())
+ strError = strVal;
+ }
+ }
+
+ LogRel(("Automatic update of Guest Additions failed: %s\n", strError.c_str()));
+ }
+
+ LogRel(("Please install Guest Additions manually\n"));
+ }
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+int SessionTaskUpdateAdditions::RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress)
+{
+ LogFlowThisFunc(("strDesc=%s, strSource=%s, uFlags=%x\n",
+ strDesc.c_str(), mSource.c_str(), mFlags));
+
+ mDesc = strDesc;
+ mProgress = pProgress;
+
+ int rc = RTThreadCreate(NULL, SessionTaskUpdateAdditions::taskThread, this,
+ 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
+ "gctlUpGA");
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+/* static */
+int SessionTaskUpdateAdditions::taskThread(RTTHREAD Thread, void *pvUser)
+{
+ std::auto_ptr<SessionTaskUpdateAdditions> task(static_cast<SessionTaskUpdateAdditions*>(pvUser));
+ AssertReturn(task.get(), VERR_GENERAL_FAILURE);
+
+ LogFlowFunc(("pTask=%p\n", task.get()));
+ return task->Run();
+}
+
diff --git a/src/VBox/Main/src-client/HGCM.cpp b/src/VBox/Main/src-client/HGCM.cpp
index c5be8f1b0..abc74a27b 100644
--- a/src/VBox/Main/src-client/HGCM.cpp
+++ b/src/VBox/Main/src-client/HGCM.cpp
@@ -789,12 +789,15 @@ int HGCMService::instanceCreate (const char *pszServiceLibrary, const char *pszS
LogFlowFunc(("name %s, lib %s\n", pszServiceName, pszServiceLibrary));
/* The maximum length of the thread name, allowed by the RT is 15. */
- char achThreadName[16];
-
- strncpy (achThreadName, pszServiceName, 15);
- achThreadName[15] = 0;
+ char szThreadName[16];
+ if (!strncmp (pszServiceName, "VBoxShared", 10))
+ RTStrPrintf (szThreadName, sizeof (szThreadName), "Sh%s", pszServiceName + 10);
+ else if (!strncmp (pszServiceName, "VBox", 4))
+ RTStrCopy (szThreadName, sizeof (szThreadName), pszServiceName + 4);
+ else
+ RTStrCopy (szThreadName, sizeof (szThreadName), pszServiceName);
- int rc = hgcmThreadCreate (&m_thread, achThreadName, hgcmServiceThread, this);
+ int rc = hgcmThreadCreate (&m_thread, szThreadName, hgcmServiceThread, this);
if (RT_SUCCESS(rc))
{
diff --git a/src/VBox/Main/src-client/MachineDebuggerImpl.cpp b/src/VBox/Main/src-client/MachineDebuggerImpl.cpp
index 899965b80..11dd820ac 100644
--- a/src/VBox/Main/src-client/MachineDebuggerImpl.cpp
+++ b/src/VBox/Main/src-client/MachineDebuggerImpl.cpp
@@ -85,7 +85,7 @@ HRESULT MachineDebugger::init (Console *aParent)
unconst(mParent) = aParent;
- mSinglestepQueued = ~0;
+ mSingleStepQueued = ~0;
mRecompileUserQueued = ~0;
mRecompileSupervisorQueued = ~0;
mPatmEnabledQueued = ~0;
@@ -124,39 +124,57 @@ void MachineDebugger::uninit()
* Returns the current singlestepping flag.
*
* @returns COM status code
- * @param aEnabled address of result variable
+ * @param a_fEnabled Where to store the result.
*/
-STDMETHODIMP MachineDebugger::COMGETTER(Singlestep) (BOOL *aEnabled)
+STDMETHODIMP MachineDebugger::COMGETTER(SingleStep)(BOOL *a_fEnabled)
{
- CheckComArgOutPointerValid(aEnabled);
+ CheckComArgOutPointerValid(a_fEnabled);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /** @todo */
- ReturnComNotImplemented();
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ Console::SafeVMPtr ptrVM(mParent);
+ hrc = ptrVM.rc();
+ if (SUCCEEDED(hrc))
+ {
+ /** @todo */
+ ReturnComNotImplemented();
+ }
+ }
+ return hrc;
}
/**
* Sets the singlestepping flag.
*
* @returns COM status code
- * @param aEnable new singlestepping flag
+ * @param a_fEnable The new state.
*/
-STDMETHODIMP MachineDebugger::COMSETTER(Singlestep) (BOOL aEnable)
+STDMETHODIMP MachineDebugger::COMSETTER(SingleStep)(BOOL a_fEnable)
{
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /** @todo */
- ReturnComNotImplemented();
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ Console::SafeVMPtr ptrVM(mParent);
+ hrc = ptrVM.rc();
+ if (SUCCEEDED(hrc))
+ {
+ /** @todo */
+ ReturnComNotImplemented();
+ }
+ }
+ return hrc;
}
/**
* Returns the current recompile user mode code flag.
*
* @returns COM status code
- * @param aEnabled address of result variable
+ * @param a_fEnabled address of result variable
*/
STDMETHODIMP MachineDebugger::COMGETTER(RecompileUser) (BOOL *aEnabled)
{
@@ -446,19 +464,128 @@ STDMETHODIMP MachineDebugger::COMSETTER(LogEnabled) (BOOL aEnabled)
return S_OK;
}
-STDMETHODIMP MachineDebugger::COMGETTER(LogFlags)(BSTR *a_pbstrSettings)
+HRESULT MachineDebugger::logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr,
+ const char *pszLogGetStr, BSTR *a_pbstrSettings)
{
- ReturnComNotImplemented();
+ /* Make sure the VM is powered up. */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ Console::SafeVMPtr ptrVM(mParent);
+ HRESULT hrc = ptrVM.rc();
+ if (FAILED(hrc))
+ return hrc;
+
+ /* Make sure we've got a logger. */
+ if (!pLogger)
+ {
+ Bstr bstrEmpty;
+ bstrEmpty.cloneTo(a_pbstrSettings);
+ return S_OK;
+ }
+
+ /* Do the job. */
+ size_t cbBuf = _1K;
+ for (;;)
+ {
+ char *pszBuf = (char *)RTMemTmpAlloc(cbBuf);
+ AssertReturn(pszBuf, E_OUTOFMEMORY);
+
+ int rc = pfnLogGetStr(pLogger, pszBuf, cbBuf);
+ if (RT_SUCCESS(rc))
+ {
+ try
+ {
+ Bstr bstrRet(pszBuf);
+ bstrRet.detachTo(a_pbstrSettings);
+ hrc = S_OK;
+ }
+ catch (std::bad_alloc)
+ {
+ hrc = E_OUTOFMEMORY;
+ }
+ RTMemTmpFree(pszBuf);
+ return hrc;
+ }
+ RTMemTmpFree(pszBuf);
+ AssertReturn(rc == VERR_BUFFER_OVERFLOW, setError(VBOX_E_IPRT_ERROR, tr("%s returned %Rrc"), pszLogGetStr, rc));
+
+ /* try again with a bigger buffer. */
+ cbBuf *= 2;
+ AssertReturn(cbBuf <= _256K, setError(E_FAIL, tr("%s returns too much data"), pszLogGetStr));
+ }
}
-STDMETHODIMP MachineDebugger::COMGETTER(LogGroups)(BSTR *a_pbstrSettings)
+
+STDMETHODIMP MachineDebugger::COMGETTER(LogDbgFlags)(BSTR *a_pbstrSettings)
{
- ReturnComNotImplemented();
+ CheckComArgOutPointerValid(a_pbstrSettings);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ hrc = logStringProps(RTLogGetDefaultInstance(), RTLogGetFlags, "RTGetFlags", a_pbstrSettings);
+
+ return hrc;
}
-STDMETHODIMP MachineDebugger::COMGETTER(LogDestinations)(BSTR *a_pbstrSettings)
+STDMETHODIMP MachineDebugger::COMGETTER(LogDbgGroups)(BSTR *a_pbstrSettings)
{
- ReturnComNotImplemented();
+ CheckComArgOutPointerValid(a_pbstrSettings);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ hrc = logStringProps(RTLogGetDefaultInstance(), RTLogGetGroupSettings, "RTLogGetGroupSettings", a_pbstrSettings);
+
+ return hrc;
+}
+
+STDMETHODIMP MachineDebugger::COMGETTER(LogDbgDestinations)(BSTR *a_pbstrSettings)
+{
+ CheckComArgOutPointerValid(a_pbstrSettings);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ hrc = logStringProps(RTLogGetDefaultInstance(), RTLogGetDestinations, "RTLogGetDestinations", a_pbstrSettings);
+
+ return hrc;
+}
+
+
+STDMETHODIMP MachineDebugger::COMGETTER(LogRelFlags)(BSTR *a_pbstrSettings)
+{
+ CheckComArgOutPointerValid(a_pbstrSettings);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ hrc = logStringProps(RTLogRelDefaultInstance(), RTLogGetFlags, "RTGetFlags", a_pbstrSettings);
+
+ return hrc;
+}
+
+STDMETHODIMP MachineDebugger::COMGETTER(LogRelGroups)(BSTR *a_pbstrSettings)
+{
+ CheckComArgOutPointerValid(a_pbstrSettings);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ hrc = logStringProps(RTLogRelDefaultInstance(), RTLogGetGroupSettings, "RTLogGetGroupSettings", a_pbstrSettings);
+
+ return hrc;
+}
+
+STDMETHODIMP MachineDebugger::COMGETTER(LogRelDestinations)(BSTR *a_pbstrSettings)
+{
+ CheckComArgOutPointerValid(a_pbstrSettings);
+
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ hrc = logStringProps(RTLogRelDefaultInstance(), RTLogGetDestinations, "RTLogGetDestinations", a_pbstrSettings);
+
+ return hrc;
}
/**
@@ -642,25 +769,25 @@ STDMETHODIMP MachineDebugger::COMGETTER(PAEEnabled) (BOOL *aEnabled)
* Returns the current virtual time rate.
*
* @returns COM status code.
- * @param aPct Where to store the rate.
+ * @param a_puPct Where to store the rate.
*/
-STDMETHODIMP MachineDebugger::COMGETTER(VirtualTimeRate) (ULONG *aPct)
+STDMETHODIMP MachineDebugger::COMGETTER(VirtualTimeRate)(ULONG *a_puPct)
{
- CheckComArgOutPointerValid(aPct);
+ CheckComArgOutPointerValid(a_puPct);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- Console::SafeVMPtrQuiet pVM (mParent);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (pVM.isOk())
- *aPct = TMGetWarpDrive (pVM);
- else
- *aPct = 100;
+ Console::SafeVMPtr ptrVM(mParent);
+ hrc = ptrVM.rc();
+ if (SUCCEEDED(hrc))
+ *a_puPct = TMGetWarpDrive(ptrVM.raw());
+ }
- return S_OK;
+ return hrc;
}
/**
@@ -669,64 +796,66 @@ STDMETHODIMP MachineDebugger::COMGETTER(VirtualTimeRate) (ULONG *aPct)
* @returns COM status code.
* @param aPct Where to store the rate.
*/
-STDMETHODIMP MachineDebugger::COMSETTER(VirtualTimeRate) (ULONG aPct)
+STDMETHODIMP MachineDebugger::COMSETTER(VirtualTimeRate)(ULONG a_uPct)
{
- if (aPct < 2 || aPct > 20000)
- return E_INVALIDARG;
+ if (a_uPct < 2 || a_uPct > 20000)
+ return setError(E_INVALIDARG, tr("%u is out of range [2..20000]"), a_uPct);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- if (queueSettings())
- {
- // queue the request
- mVirtualTimeRateQueued = aPct;
- return S_OK;
- }
-
- Console::SafeVMPtr pVM(mParent);
- if (FAILED(pVM.rc())) return pVM.rc();
-
- int vrc = TMR3SetWarpDrive (pVM, aPct);
- if (RT_FAILURE(vrc))
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
{
- /** @todo handle error code. */
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (queueSettings())
+ mVirtualTimeRateQueued = a_uPct;
+ else
+ {
+ Console::SafeVMPtr ptrVM(mParent);
+ hrc = ptrVM.rc();
+ if (SUCCEEDED(hrc))
+ {
+ int vrc = TMR3SetWarpDrive(ptrVM.raw(), a_uPct);
+ if (RT_FAILURE(vrc))
+ hrc = setError(VBOX_E_VM_ERROR, tr("TMR3SetWarpDrive(, %u) failed with rc=%Rrc"), a_uPct, vrc);
+ }
+ }
}
- return S_OK;
+ return hrc;
}
/**
* Hack for getting the VM handle.
+ *
* This is only temporary (promise) while prototyping the debugger.
*
* @returns COM status code
- * @param aVm Where to store the vm handle.
- * Since there is no uintptr_t in COM, we're using the max integer.
- * (No, ULONG is not pointer sized!)
+ * @param a_u64Vm Where to store the vm handle. Since there is no
+ * uintptr_t in COM, we're using the max integer.
+ * (No, ULONG is not pointer sized!)
*/
-STDMETHODIMP MachineDebugger::COMGETTER(VM) (LONG64 *aVm)
+STDMETHODIMP MachineDebugger::COMGETTER(VM)(LONG64 *a_u64Vm)
{
- CheckComArgOutPointerValid(aVm);
+ CheckComArgOutPointerValid(a_u64Vm);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- Console::SafeVMPtr pVM(mParent);
- if (FAILED(pVM.rc())) return pVM.rc();
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aVm = (intptr_t)pVM.raw();
+ Console::SafeVMPtr ptrVM(mParent);
+ hrc = ptrVM.rc();
+ if (SUCCEEDED(hrc))
+ *a_u64Vm = (intptr_t)ptrVM.raw();
- /*
- * Note: pVM protection provided by SafeVMPtr is no more effective
- * after we return from this method.
- */
+ /*
+ * Note! pVM protection provided by SafeVMPtr is no long effective
+ * after we return from this method.
+ */
+ }
- return S_OK;
+ return hrc;
}
// IMachineDebugger methods
@@ -1338,39 +1467,39 @@ STDMETHODIMP MachineDebugger::GetStats (IN_BSTR aPattern, BOOL aWithDescriptions
void MachineDebugger::flushQueuedSettings()
{
mFlushMode = true;
- if (mSinglestepQueued != ~0)
+ if (mSingleStepQueued != ~0)
{
- COMSETTER(Singlestep) (mSinglestepQueued);
- mSinglestepQueued = ~0;
+ COMSETTER(SingleStep)(mSingleStepQueued);
+ mSingleStepQueued = ~0;
}
if (mRecompileUserQueued != ~0)
{
- COMSETTER(RecompileUser) (mRecompileUserQueued);
+ COMSETTER(RecompileUser)(mRecompileUserQueued);
mRecompileUserQueued = ~0;
}
if (mRecompileSupervisorQueued != ~0)
{
- COMSETTER(RecompileSupervisor) (mRecompileSupervisorQueued);
+ COMSETTER(RecompileSupervisor)(mRecompileSupervisorQueued);
mRecompileSupervisorQueued = ~0;
}
if (mPatmEnabledQueued != ~0)
{
- COMSETTER(PATMEnabled) (mPatmEnabledQueued);
+ COMSETTER(PATMEnabled)(mPatmEnabledQueued);
mPatmEnabledQueued = ~0;
}
if (mCsamEnabledQueued != ~0)
{
- COMSETTER(CSAMEnabled) (mCsamEnabledQueued);
+ COMSETTER(CSAMEnabled)(mCsamEnabledQueued);
mCsamEnabledQueued = ~0;
}
if (mLogEnabledQueued != ~0)
{
- COMSETTER(LogEnabled) (mLogEnabledQueued);
+ COMSETTER(LogEnabled)(mLogEnabledQueued);
mLogEnabledQueued = ~0;
}
if (mVirtualTimeRateQueued != ~(uint32_t)0)
{
- COMSETTER(VirtualTimeRate) (mVirtualTimeRateQueued);
+ COMSETTER(VirtualTimeRate)(mVirtualTimeRateQueued);
mVirtualTimeRateQueued = ~0;
}
mFlushMode = false;
@@ -1385,7 +1514,7 @@ bool MachineDebugger::queueSettings() const
{
// check if the machine is running
MachineState_T machineState;
- mParent->COMGETTER(State) (&machineState);
+ mParent->COMGETTER(State)(&machineState);
switch (machineState)
{
// queue the request
diff --git a/src/VBox/Main/src-client/MouseImpl.cpp b/src/VBox/Main/src-client/MouseImpl.cpp
index eb90e66f2..641f1ad8d 100644
--- a/src/VBox/Main/src-client/MouseImpl.cpp
+++ b/src/VBox/Main/src-client/MouseImpl.cpp
@@ -40,18 +40,6 @@ enum
};
/** @} */
-/** @name Absolute mouse reporting range
- * @{ */
-enum
-{
- /** Lower end */
- MOUSE_RANGE_LOWER = 0,
- /** Higher end */
- MOUSE_RANGE_UPPER = 0xFFFF,
- /** Full range */
- MOUSE_RANGE = MOUSE_RANGE_UPPER - MOUSE_RANGE_LOWER
-};
-/** @} */
/**
* Mouse driver instance data.
@@ -179,7 +167,8 @@ HRESULT Mouse::updateVMMDevMouseCaps(uint32_t fCapsAdded,
return E_FAIL; /* No assertion, as the front-ends can send events
* at all sorts of inconvenient times. */
PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
- ComAssertRet(pVMMDevPort, E_FAIL);
+ if (!pVMMDevPort)
+ return E_FAIL; /* same here */
int rc = pVMMDevPort->pfnUpdateMouseCapabilities(pVMMDevPort, fCapsAdded,
fCapsRemoved);
@@ -326,9 +315,11 @@ HRESULT Mouse::reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz,
HRESULT Mouse::reportAbsEventToMouseDev(int32_t mouseXAbs, int32_t mouseYAbs,
int32_t dz, int32_t dw, uint32_t fButtons)
{
- if (mouseXAbs < MOUSE_RANGE_LOWER || mouseXAbs > MOUSE_RANGE_UPPER)
+ if ( mouseXAbs < VMMDEV_MOUSE_RANGE_MIN
+ || mouseXAbs > VMMDEV_MOUSE_RANGE_MAX)
return S_OK;
- if (mouseYAbs < MOUSE_RANGE_LOWER || mouseYAbs > MOUSE_RANGE_UPPER)
+ if ( mouseYAbs < VMMDEV_MOUSE_RANGE_MIN
+ || mouseYAbs > VMMDEV_MOUSE_RANGE_MAX)
return S_OK;
if ( mouseXAbs != mcLastAbsX || mouseYAbs != mcLastAbsY
|| dz || dw || fButtons != mfLastButtons)
@@ -476,9 +467,9 @@ STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw, LONG butto
/**
* Convert an (X, Y) value pair in screen co-ordinates (starting from 1) to a
- * value from MOUSE_RANGE_LOWER to MOUSE_RANGE_UPPER. Sets the optional
- * validity value to false if the pair is not on an active screen and to true
- * otherwise.
+ * value from VMMDEV_MOUSE_RANGE_MIN to VMMDEV_MOUSE_RANGE_MAX. Sets the
+ * optional validity value to false if the pair is not on an active screen and
+ * to true otherwise.
* @note since guests with recent versions of X.Org use a different method
* to everyone else to map the valuator value to a screen pixel (they
* multiply by the screen dimension, do a floating point divide by
@@ -500,7 +491,7 @@ HRESULT Mouse::convertDisplayRes(LONG x, LONG y, int32_t *pcX, int32_t *pcY,
/** The amount to add to the result (multiplied by the screen width/height)
* to compensate for differences in guest methods for mapping back to
* pixels */
- enum { ADJUST_RANGE = - 3 * MOUSE_RANGE / 4 };
+ enum { ADJUST_RANGE = - 3 * VMMDEV_MOUSE_RANGE / 4 };
if (pfValid)
*pfValid = true;
@@ -508,23 +499,27 @@ HRESULT Mouse::convertDisplayRes(LONG x, LONG y, int32_t *pcX, int32_t *pcY,
{
ULONG displayWidth, displayHeight;
/* Takes the display lock */
- HRESULT rc = pDisplay->GetScreenResolution(0, &displayWidth, &displayHeight,
- NULL);
+ HRESULT rc = pDisplay->GetScreenResolution(0, &displayWidth,
+ &displayHeight, NULL);
if (FAILED(rc))
return rc;
- *pcX = displayWidth ? (x * MOUSE_RANGE + ADJUST_RANGE) / (LONG) displayWidth: 0;
- *pcY = displayHeight ? (y * MOUSE_RANGE + ADJUST_RANGE) / (LONG) displayHeight: 0;
+ *pcX = displayWidth ? (x * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
+ / (LONG) displayWidth: 0;
+ *pcY = displayHeight ? (y * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
+ / (LONG) displayHeight: 0;
}
else
{
int32_t x1, y1, x2, y2;
/* Takes the display lock */
pDisplay->getFramebufferDimensions(&x1, &y1, &x2, &y2);
- *pcX = x1 < x2 ? ((x - x1) * MOUSE_RANGE + ADJUST_RANGE) / (x2 - x1) : 0;
- *pcY = y1 < y2 ? ((y - y1) * MOUSE_RANGE + ADJUST_RANGE) / (y2 - y1) : 0;
- if ( *pcX < MOUSE_RANGE_LOWER || *pcX > MOUSE_RANGE_UPPER
- || *pcY < MOUSE_RANGE_LOWER || *pcY > MOUSE_RANGE_UPPER)
+ *pcX = x1 < x2 ? ((x - x1) * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
+ / (x2 - x1) : 0;
+ *pcY = y1 < y2 ? ((y - y1) * VMMDEV_MOUSE_RANGE + ADJUST_RANGE)
+ / (y2 - y1) : 0;
+ if ( *pcX < VMMDEV_MOUSE_RANGE_MIN || *pcX > VMMDEV_MOUSE_RANGE_MAX
+ || *pcY < VMMDEV_MOUSE_RANGE_MIN || *pcY > VMMDEV_MOUSE_RANGE_MAX)
if (pfValid)
*pfValid = false;
}
diff --git a/src/VBox/Main/src-client/Nvram.cpp b/src/VBox/Main/src-client/Nvram.cpp
new file mode 100644
index 000000000..d1c2a8a4e
--- /dev/null
+++ b/src/VBox/Main/src-client/Nvram.cpp
@@ -0,0 +1,331 @@
+/* $Id: Nvram.cpp $ */
+/** @file
+ * VBox NVRAM COM Class implementation.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "Nvram.h"
+#include "ConsoleImpl.h"
+
+#include <VBox/vmm/pdm.h>
+#include <VBox/vmm/pdmdrv.h>
+#include <VBox/vmm/pdmnvram.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/log.h>
+#include <VBox/err.h>
+#include <iprt/assert.h>
+#include <iprt/critsect.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/uuid.h>
+#include <iprt/base64.h>
+#include <VBox/version.h>
+#include <iprt/file.h>
+#include <iprt/semaphore.h>
+
+
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
+typedef struct NVRAM NVRAM;
+typedef struct NVRAM *PNVRAM;
+
+struct NVRAM
+{
+ Nvram *pNvram;
+ PDMINVRAM INvram;
+ int cLoadedVariables;
+ bool fPermanentSave;
+};
+
+
+/**
+ * Constructor/destructor
+ */
+Nvram::Nvram(Console *console)
+ : mpDrv(NULL),
+ mParent(console)
+{
+}
+
+Nvram::~Nvram()
+{
+ if (mpDrv)
+ {
+ mpDrv->pNvram = NULL;
+ mpDrv = NULL;
+ }
+}
+
+
+/**
+ * @interface_method_impl(PDMINVRAM,pfnStoreNvramValue)
+ */
+DECLCALLBACK(int) drvNvram_pfnStoreNvramValue(PPDMINVRAM pInterface,
+ int idxVariable,
+ RTUUID *pVendorUuid,
+ const char *pcszVariableName,
+ size_t cbVariableName,
+ uint8_t *pu8Value,
+ size_t cbValue)
+{
+ int rc = VINF_SUCCESS;
+ char szExtraDataKey[256];
+ char szExtraDataValue[1024];
+ LogFlowFunc(("ENTER: pVendorUuid:%RTuuid, pcszVariableName:%s, cbVariableName:%d, pu8Value:%.*Rhxs, cbValue:%d\n",
+ pVendorUuid,
+ pcszVariableName,
+ cbVariableName,
+ cbValue,
+ pu8Value,
+ cbValue));
+ PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram);
+ if (!pThis->fPermanentSave)
+ {
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+ }
+
+ bool fFlushVariable = (!pu8Value);
+
+ RT_ZERO(szExtraDataKey);
+ RT_ZERO(szExtraDataValue);
+ RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableName", idxVariable);
+ if (!fFlushVariable)
+ RTStrPrintf(szExtraDataValue, 1024, "%s", pcszVariableName);
+ pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw());
+
+ RT_ZERO(szExtraDataKey);
+ RT_ZERO(szExtraDataValue);
+ RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VendorGuid", idxVariable);
+ if (!fFlushVariable)
+ RTUuidToStr(pVendorUuid, szExtraDataValue, 1024);
+ pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw());
+
+ RT_ZERO(szExtraDataKey);
+ RT_ZERO(szExtraDataValue);
+ RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValueLength", idxVariable);
+ if (!fFlushVariable)
+ RTStrPrintf(szExtraDataValue, 1024, "%d", cbValue);
+ pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw());
+
+ RT_ZERO(szExtraDataKey);
+ RT_ZERO(szExtraDataValue);
+ RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValue", idxVariable);
+ size_t cbActualSize;
+ if (pu8Value)
+ rc = RTBase64Encode(pu8Value, cbValue, szExtraDataValue, 1024, &cbActualSize);
+ AssertRCReturn(rc, rc);
+ pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw());
+
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+
+/**
+ * @interface_method_impl(PDMINVRAM,pfnFlushNvramStorage)
+ */
+DECLCALLBACK(int) drvNvram_pfnFlushNvramStorage(PPDMINVRAM pInterface)
+{
+ int rc = VINF_SUCCESS;
+ LogFlowFuncEnter();
+ PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram);
+ if (!pThis->fPermanentSave)
+ {
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+ }
+
+ for (int idxVariable = 0; idxVariable < pThis->cLoadedVariables; ++idxVariable)
+ {
+ drvNvram_pfnStoreNvramValue(pInterface, idxVariable, NULL, NULL, 0, NULL, 0);
+ }
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+
+/**
+ * @interface_method_impl(PDMINVRAM,pfnStoreNvramValue)
+ */
+DECLCALLBACK(int) drvNvram_pfnLoadNvramValue(PPDMINVRAM pInterface,
+ int idxVariable,
+ RTUUID *pVendorUuid,
+ char *pcszVariableName,
+ size_t *pcbVariableName,
+ uint8_t *pu8Value,
+ size_t *pcbValue)
+{
+ int rc = VINF_SUCCESS;
+ char szExtraDataKey[256];
+ Bstr bstrValue;
+ HRESULT hrc;
+ LogFlowFunc(("ENTER: idxVariable:%d, *pcbVariableName:%d, *pcbValue:%d\n",
+ idxVariable,
+ *pcbVariableName,
+ *pcbValue));
+ PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram);
+ if (!pThis->fPermanentSave)
+ {
+ rc = VERR_NOT_FOUND;
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+ }
+
+
+ RT_ZERO(szExtraDataKey);
+ RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableName", idxVariable);
+ hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam());
+ if (!SUCCEEDED(hrc))
+ return VERR_NOT_FOUND;
+ *pcbVariableName = RTStrCopy(pcszVariableName, 1024, Utf8Str(bstrValue).c_str());
+
+ RT_ZERO(szExtraDataKey);
+ RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VendorGuid", idxVariable);
+ hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam());
+ RTUuidFromStr(pVendorUuid, Utf8Str(bstrValue).c_str());
+
+#if 0
+ RT_ZERO(szExtraDataKey);
+ RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValueLength", idxVariable);
+ hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam());
+ *pcbValue = Utf8Str(bstrValue).toUInt32();
+#endif
+
+ RT_ZERO(szExtraDataKey);
+ RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValue", idxVariable);
+ hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam());
+ rc = RTBase64Decode(Utf8Str(bstrValue).c_str(), pu8Value, 1024, pcbValue, NULL);
+ AssertRCReturn(rc, rc);
+
+ pThis->cLoadedVariables++;
+ LogFlowFuncLeaveRC(rc);
+ return rc;
+}
+
+
+/**
+ * @interface_method_impl(PDMIBASE,pfnQueryInterface)
+ */
+DECLCALLBACK(void *) Nvram::drvNvram_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+ LogFlow(("%s pInterface:%p, pszIID:%s\n", __FUNCTION__, pInterface, pszIID));
+ PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
+ PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
+
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMINVRAM, &pThis->INvram);
+ return NULL;
+}
+
+
+/**
+ * @interface_method_impl(PDMDRVREG,pfnDestruct)
+ */
+DECLCALLBACK(void) Nvram::drvNvram_Destruct(PPDMDRVINS pDrvIns)
+{
+ LogFlow(("%s: iInstance/#d\n", __FUNCTION__, pDrvIns->iInstance));
+ PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
+}
+
+
+/**
+ * @interface_method_impl(PDMDRVREG,pfnConstruct)
+ */
+DECLCALLBACK(int) Nvram::drvNvram_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
+{
+ LogFlowFunc(("iInstance/#d, pCfg:%p, fFlags:%x\n", pDrvIns->iInstance, pCfg, fFlags));
+ PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
+
+ if (!CFGMR3AreValuesValid(pCfg, "Object\0"
+ "PermanentSave\0"))
+ return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
+ AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
+ ("Configuration error: Not possible to attach anything to this driver!\n"),
+ VERR_PDM_DRVINS_NO_ATTACH);
+
+ void *pv;
+ int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
+ AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc);
+ pThis->pNvram = (Nvram *)pv;
+
+ bool fPermanentSave = false;
+ rc = CFGMR3QueryBool(pCfg, "PermanentSave", &fPermanentSave);
+ if ( RT_SUCCESS(rc)
+ || rc == VERR_CFGM_VALUE_NOT_FOUND)
+ pThis->fPermanentSave = fPermanentSave;
+ else
+ AssertRCReturn(rc, rc);
+
+ pDrvIns->IBase.pfnQueryInterface = Nvram::drvNvram_QueryInterface;
+ pThis->INvram.pfnFlushNvramStorage = drvNvram_pfnFlushNvramStorage;
+ pThis->INvram.pfnStoreNvramValue = drvNvram_pfnStoreNvramValue;
+ pThis->INvram.pfnLoadNvramValue = drvNvram_pfnLoadNvramValue;
+
+ return VINF_SUCCESS;
+}
+
+
+const PDMDRVREG Nvram::DrvReg =
+{
+ /* u32Version */
+ PDM_DRVREG_VERSION,
+ /* szName[32] */
+ "NvramStorage",
+ /* szRCMod[32] */
+ "",
+ /* szR0Mod[32] */
+ "",
+ /* pszDescription */
+ "NVRAM Main Driver",
+ /* fFlags */
+ PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
+ /* fClass */
+ PDM_DRVREG_CLASS_VMMDEV,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(NVRAM),
+ /* pfnConstruct */
+ Nvram::drvNvram_Construct,
+ /* pfnDestruct */
+ Nvram::drvNvram_Destruct,
+ /* pfnRelocate */
+ NULL,
+ /* pfnIOCtl */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ NULL,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DRVREG_VERSION
+};
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/src-client/PciRawDevImpl.cpp b/src/VBox/Main/src-client/PCIRawDevImpl.cpp
index a8d723aa5..35617c8a8 100644
--- a/src/VBox/Main/src-client/PciRawDevImpl.cpp
+++ b/src/VBox/Main/src-client/PCIRawDevImpl.cpp
@@ -1,10 +1,10 @@
-/* $Id: PciRawDevImpl.cpp $ */
+/* $Id: PCIRawDevImpl.cpp $ */
/** @file
* VirtualBox Driver Interface to raw PCI device.
*/
/*
- * Copyright (C) 2010-2011 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -15,8 +15,8 @@
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "Logging.h"
-#include "PciRawDevImpl.h"
-#include "PciDeviceAttachmentImpl.h"
+#include "PCIRawDevImpl.h"
+#include "PCIDeviceAttachmentImpl.h"
#include "ConsoleImpl.h"
#include "MachineImpl.h"
@@ -29,7 +29,7 @@
typedef struct DRVMAINPCIRAWDEV
{
/** Pointer to the real PCI raw object. */
- PciRawDev *pPciRawDev;
+ PCIRawDev *pPCIRawDev;
/** Pointer to the driver instance structure. */
PPDMDRVINS pDrvIns;
/** Our PCI device connector interface. */
@@ -40,20 +40,20 @@ typedef struct DRVMAINPCIRAWDEV
//
// constructor / destructor
//
-PciRawDev::PciRawDev(Console *console)
+PCIRawDev::PCIRawDev(Console *console)
: mpDrv(NULL),
mParent(console)
{
}
-PciRawDev::~PciRawDev()
+PCIRawDev::~PCIRawDev()
{
}
/**
* @interface_method_impl{PDMIBASE,pfnQueryInterface}
*/
-DECLCALLBACK(void *) PciRawDev::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+DECLCALLBACK(void *) PCIRawDev::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
PDRVMAINPCIRAWDEV pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINPCIRAWDEV);
@@ -68,12 +68,12 @@ DECLCALLBACK(void *) PciRawDev::drvQueryInterface(PPDMIBASE pInterface, const ch
/**
* @interface_method_impl{PDMIPCIRAWUP,pfnPciDeviceConstructComplete}
*/
-DECLCALLBACK(int) PciRawDev::drvDeviceConstructComplete(PPDMIPCIRAWCONNECTOR pInterface, const char *pcszName,
- uint32_t uHostPciAddress, uint32_t uGuestPciAddress,
+DECLCALLBACK(int) PCIRawDev::drvDeviceConstructComplete(PPDMIPCIRAWCONNECTOR pInterface, const char *pcszName,
+ uint32_t uHostPCIAddress, uint32_t uGuestPCIAddress,
int rc)
{
PDRVMAINPCIRAWDEV pThis = RT_FROM_CPP_MEMBER(pInterface, DRVMAINPCIRAWDEV, IConnector);
- Console *pConsole = pThis->pPciRawDev->getParent();
+ Console *pConsole = pThis->pPCIRawDev->getParent();
const ComPtr<IMachine>& machine = pConsole->machine();
ComPtr<IVirtualBox> vbox;
@@ -88,16 +88,16 @@ DECLCALLBACK(int) PciRawDev::drvDeviceConstructComplete(PPDMIPCIRAWCONNECTOR pIn
hrc = machine->COMGETTER(Id)(bstrId.asOutParam());
Assert(SUCCEEDED(hrc));
- ComObjPtr<PciDeviceAttachment> pda;
+ ComObjPtr<PCIDeviceAttachment> pda;
BstrFmt bstrName(pcszName);
pda.createObject();
- pda->init(machine, bstrName, uHostPciAddress, uGuestPciAddress, TRUE);
+ pda->init(machine, bstrName, uHostPCIAddress, uGuestPCIAddress, TRUE);
Bstr msg("");
if (RT_FAILURE(rc))
msg = BstrFmt("runtime error %Rrc", rc);
- fireHostPciDevicePlugEvent(es, bstrId.raw(), true /* plugged */, RT_SUCCESS(rc) /* success */, pda, msg.raw());
+ fireHostPCIDevicePlugEvent(es, bstrId.raw(), true /* plugged */, RT_SUCCESS(rc) /* success */, pda, msg.raw());
return VINF_SUCCESS;
}
@@ -109,13 +109,13 @@ DECLCALLBACK(int) PciRawDev::drvDeviceConstructComplete(PPDMIPCIRAWCONNECTOR pIn
* @returns VBox status.
* @param pDrvIns The driver instance data.
*/
-DECLCALLBACK(void) PciRawDev::drvDestruct(PPDMDRVINS pDrvIns)
+DECLCALLBACK(void) PCIRawDev::drvDestruct(PPDMDRVINS pDrvIns)
{
PDRVMAINPCIRAWDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINPCIRAWDEV);
PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
- if (pData->pPciRawDev)
- pData->pPciRawDev->mpDrv = NULL;
+ if (pData->pPCIRawDev)
+ pData->pPCIRawDev->mpDrv = NULL;
}
@@ -125,7 +125,7 @@ DECLCALLBACK(void) PciRawDev::drvDestruct(PPDMDRVINS pDrvIns)
* @returns VBox status.
* @param pDrvIns The driver instance data.
*/
-DECLCALLBACK(void) PciRawDev::drvReset(PPDMDRVINS pDrvIns)
+DECLCALLBACK(void) PCIRawDev::drvReset(PPDMDRVINS pDrvIns)
{
}
@@ -135,7 +135,7 @@ DECLCALLBACK(void) PciRawDev::drvReset(PPDMDRVINS pDrvIns)
*
* @copydoc FNPDMDRVCONSTRUCT
*/
-DECLCALLBACK(int) PciRawDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
+DECLCALLBACK(int) PCIRawDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
{
PDRVMAINPCIRAWDEV pData = PDMINS_2_DATA(pDrvIns, PDRVMAINPCIRAWDEV);
PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
@@ -153,12 +153,12 @@ DECLCALLBACK(int) PciRawDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHand
/*
* IBase.
*/
- pDrvIns->IBase.pfnQueryInterface = PciRawDev::drvQueryInterface;
+ pDrvIns->IBase.pfnQueryInterface = PCIRawDev::drvQueryInterface;
/*
* IConnector.
*/
- pData->IConnector.pfnDeviceConstructComplete = PciRawDev::drvDeviceConstructComplete;
+ pData->IConnector.pfnDeviceConstructComplete = PCIRawDev::drvDeviceConstructComplete;
/*
* Get the object pointer and update the mpDrv member.
@@ -171,8 +171,8 @@ DECLCALLBACK(int) PciRawDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHand
return rc;
}
- pData->pPciRawDev = (PciRawDev*)pv;
- pData->pPciRawDev->mpDrv = pData;
+ pData->pPCIRawDev = (PCIRawDev *)pv;
+ pData->pPCIRawDev->mpDrv = pData;
return VINF_SUCCESS;
}
@@ -180,7 +180,7 @@ DECLCALLBACK(int) PciRawDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHand
/**
* Main raw PCI driver registration record.
*/
-const PDMDRVREG PciRawDev::DrvReg =
+const PDMDRVREG PCIRawDev::DrvReg =
{
/* u32Version */
PDM_DRVREG_VERSION,
@@ -201,9 +201,9 @@ const PDMDRVREG PciRawDev::DrvReg =
/* cbInstance */
sizeof(DRVMAINPCIRAWDEV),
/* pfnConstruct */
- PciRawDev::drvConstruct,
+ PCIRawDev::drvConstruct,
/* pfnDestruct */
- PciRawDev::drvDestruct,
+ PCIRawDev::drvDestruct,
/* pfnRelocate */
NULL,
/* pfnIOCtl */
@@ -211,7 +211,7 @@ const PDMDRVREG PciRawDev::DrvReg =
/* pfnPowerOn */
NULL,
/* pfnReset */
- PciRawDev::drvReset,
+ PCIRawDev::drvReset,
/* pfnSuspend */
NULL,
/* pfnResume */
diff --git a/src/VBox/Main/src-client/SessionImpl.cpp b/src/VBox/Main/src-client/SessionImpl.cpp
index 954f65c2b..5c0305509 100644
--- a/src/VBox/Main/src-client/SessionImpl.cpp
+++ b/src/VBox/Main/src-client/SessionImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -299,7 +299,7 @@ STDMETHODIMP Session::GetRemoteConsole(IConsole **aConsole)
return S_OK;
}
-STDMETHODIMP Session::AssignMachine(IMachine *aMachine)
+STDMETHODIMP Session::AssignMachine(IMachine *aMachine, LockType_T aLockType)
{
LogFlowThisFuncEnter();
LogFlowThisFunc(("aMachine=%p\n", aMachine));
@@ -336,7 +336,7 @@ STDMETHODIMP Session::AssignMachine(IMachine *aMachine)
rc = mConsole.createObject();
AssertComRCReturn(rc, rc);
- rc = mConsole->init(aMachine, mControl);
+ rc = mConsole->init(aMachine, mControl, aLockType);
AssertComRCReturn(rc, rc);
rc = grabIPCSemaphore();
@@ -357,8 +357,11 @@ STDMETHODIMP Session::AssignMachine(IMachine *aMachine)
{
/* some cleanup */
mControl.setNull();
- mConsole->uninit();
- mConsole.setNull();
+ if (!mConsole.isNull())
+ {
+ mConsole->uninit();
+ mConsole.setNull();
+ }
}
LogFlowThisFunc(("rc=%08X\n", rc));
@@ -492,8 +495,10 @@ STDMETHODIMP Session::Uninitialize()
return S_OK;
}
+#ifndef DEBUG_andy /* Don't bug me -- now time to fix this at the moment. */
AssertReturn(mState == SessionState_Locked ||
- mState == SessionState_Spawning, VBOX_E_INVALID_VM_STATE);
+ mState == SessionState_Spawning, VBOX_E_INVALID_VM_STATE);
+#endif
/* close ourselves */
rc = unlockMachine(false /* aFinalRelease */, true /* aFromServer */);
@@ -528,6 +533,7 @@ STDMETHODIMP Session::OnNetworkAdapterChange(INetworkAdapter *networkAdapter, BO
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onNetworkAdapterChange(networkAdapter, changeAdapter);
}
@@ -542,6 +548,7 @@ STDMETHODIMP Session::OnSerialPortChange(ISerialPort *serialPort)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onSerialPortChange(serialPort);
}
@@ -556,6 +563,7 @@ STDMETHODIMP Session::OnParallelPortChange(IParallelPort *parallelPort)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onParallelPortChange(parallelPort);
}
@@ -570,6 +578,7 @@ STDMETHODIMP Session::OnStorageControllerChange()
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onStorageControllerChange();
}
@@ -584,6 +593,7 @@ STDMETHODIMP Session::OnMediumChange(IMediumAttachment *aMediumAttachment, BOOL
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onMediumChange(aMediumAttachment, aForce);
}
@@ -598,6 +608,7 @@ STDMETHODIMP Session::OnCPUChange(ULONG aCPU, BOOL aRemove)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onCPUChange(aCPU, aRemove);
}
@@ -612,6 +623,7 @@ STDMETHODIMP Session::OnCPUExecutionCapChange(ULONG aExecutionCap)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onCPUExecutionCapChange(aExecutionCap);
}
@@ -626,6 +638,7 @@ STDMETHODIMP Session::OnVRDEServerChange(BOOL aRestart)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onVRDEServerChange(aRestart);
}
@@ -640,6 +653,7 @@ STDMETHODIMP Session::OnUSBControllerChange()
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onUSBControllerChange();
}
@@ -654,10 +668,40 @@ STDMETHODIMP Session::OnSharedFolderChange(BOOL aGlobal)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onSharedFolderChange(aGlobal);
}
+STDMETHODIMP Session::OnClipboardModeChange(ClipboardMode_T aClipboardMode)
+{
+ LogFlowThisFunc(("\n"));
+
+ AutoCaller autoCaller(this);
+ AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
+ AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
+
+ return mConsole->onClipboardModeChange(aClipboardMode);
+}
+
+STDMETHODIMP Session::OnDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode)
+{
+ LogFlowThisFunc(("\n"));
+
+ AutoCaller autoCaller(this);
+ AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
+ AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+
+ return mConsole->onDragAndDropModeChange(aDragAndDropMode);
+}
+
STDMETHODIMP Session::OnUSBDeviceAttach(IUSBDevice *aDevice,
IVirtualBoxErrorInfo *aError,
ULONG aMaskedIfs)
@@ -670,6 +714,7 @@ STDMETHODIMP Session::OnUSBDeviceAttach(IUSBDevice *aDevice,
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onUSBDeviceAttach(aDevice, aError, aMaskedIfs);
}
@@ -685,6 +730,7 @@ STDMETHODIMP Session::OnUSBDeviceDetach(IN_BSTR aId,
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onUSBDeviceDetach(aId, aError);
}
@@ -697,6 +743,7 @@ STDMETHODIMP Session::OnShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
if (mState != SessionState_Locked)
{
@@ -722,6 +769,7 @@ STDMETHODIMP Session::OnBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onBandwidthGroupChange(aBandwidthGroup);
}
@@ -736,6 +784,7 @@ STDMETHODIMP Session::OnStorageDeviceChange(IMediumAttachment *aMediumAttachment
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
return mConsole->onStorageDeviceChange(aMediumAttachment, aRemove);
}
@@ -765,6 +814,12 @@ STDMETHODIMP Session::AccessGuestProperty(IN_BSTR aName, IN_BSTR aValue, IN_BSTR
/* aFlags can be null if it is to be left as is */
if (aIsSetter && (aFlags != NULL) && !VALID_PTR(aFlags))
return E_INVALIDARG;
+
+ /* If this session is not in a VM process fend off the call. The caller
+ * handles this correctly, by doing the operation in VBoxSVC. */
+ if (!mConsole)
+ return E_ACCESSDENIED;
+
if (!aIsSetter)
return mConsole->getGuestProperty(aName, aRetValue, aRetTimestamp, aRetFlags);
else
@@ -799,6 +854,12 @@ STDMETHODIMP Session::EnumerateGuestProperties(IN_BSTR aPatterns,
return E_POINTER;
if (ComSafeArrayOutIsNull(aFlags))
return E_POINTER;
+
+ /* If this session is not in a VM process fend off the call. The caller
+ * handles this correctly, by doing the operation in VBoxSVC. */
+ if (!mConsole)
+ return E_ACCESSDENIED;
+
return mConsole->enumerateGuestProperties(aPatterns,
ComSafeArrayOutArg(aNames),
ComSafeArrayOutArg(aValues),
@@ -825,6 +886,7 @@ STDMETHODIMP Session::OnlineMergeMedium(IMediumAttachment *aMediumAttachment,
tr("Machine is not locked by session (session state: %s)."),
Global::stringifySessionState(mState));
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
CheckComArgNotNull(aMediumAttachment);
CheckComArgSafeArrayNotNull(aChildrenToReparent);
@@ -843,6 +905,7 @@ STDMETHODIMP Session::EnableVMMStatistics(BOOL aEnable)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+ AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
mConsole->enableVMMStatistics(aEnable);
@@ -909,8 +972,11 @@ HRESULT Session::unlockMachine(bool aFinalRelease, bool aFromServer)
if (mType == SessionType_WriteLock)
{
- mConsole->uninit();
- mConsole.setNull();
+ if (!mConsole.isNull())
+ {
+ mConsole->uninit();
+ mConsole.setNull();
+ }
}
else
{
@@ -939,13 +1005,13 @@ HRESULT Session::unlockMachine(bool aFinalRelease, bool aFromServer)
* we need to release the lock to avoid deadlocks. The state is already
* SessionState_Closing here, so it's safe.
*/
- alock.leave();
+ alock.release();
LogFlowThisFunc(("Calling mControl->OnSessionEnd()...\n"));
HRESULT rc = mControl->OnSessionEnd(this, progress.asOutParam());
LogFlowThisFunc(("mControl->OnSessionEnd()=%08X\n", rc));
- alock.enter();
+ alock.acquire();
/*
* If we get E_UNEXPECTED this means that the direct session has already
diff --git a/src/VBox/Main/src-client/UsbCardReader.cpp b/src/VBox/Main/src-client/UsbCardReader.cpp
index c2a847799..f7a7bc5bc 100644
--- a/src/VBox/Main/src-client/UsbCardReader.cpp
+++ b/src/VBox/Main/src-client/UsbCardReader.cpp
@@ -30,14 +30,6 @@
#include <iprt/req.h>
-#define NIL_RTREQQUEUE ((RTREQQUEUE *)0)
-#define RTReqQueueCallEx RTReqCallEx
-#define RTReqQueueProcess RTReqProcess
-#define RTReqQueueCall RTReqCall
-#define RTReqQueueCreate RTReqCreateQueue
-#define RTReqQueueDestroy RTReqDestroyQueue
-#define RTReqRelease RTReqFree
-
/*******************************************************************************
* Structures and Typedefs *
@@ -57,7 +49,7 @@ struct USBCARDREADER
/* Thread handling Cmd to card reader */
PPDMTHREAD pThrCardReaderCmd;
/* Queue handling requests to cardreader */
- RTREQQUEUE *hReqQCardReaderCmd;
+ RTREQQUEUE hReqQCardReaderCmd;
};
@@ -346,9 +338,9 @@ static DECLCALLBACK(int) drvCardReaderDownConnect(PPDMICARDREADERDOWN pInterface
return rc;
}
-static DECLCALLBACK(int)drvCardReaderDownDisconnect(PPDMICARDREADERDOWN pInterface,
- void *pvUser,
- uint32_t u32Disposition)
+static DECLCALLBACK(int) drvCardReaderDownDisconnect(PPDMICARDREADERDOWN pInterface,
+ void *pvUser,
+ uint32_t u32Disposition)
{
AssertPtrReturn(pInterface, VERR_INVALID_PARAMETER);
LogFlowFunc(("ENTER: pvUser:%p, u32Disposition:%RX32\n",
@@ -397,10 +389,10 @@ static DECLCALLBACK(int) drvCardReaderDownReleaseContext(PPDMICARDREADERDOWN pIn
return rc;
}
-static DECLCALLBACK(int)drvCardReaderDownStatus(PPDMICARDREADERDOWN pInterface,
- void *pvUser,
- uint32_t cchReaderName,
- uint32_t cbAtrLen)
+static DECLCALLBACK(int) drvCardReaderDownStatus(PPDMICARDREADERDOWN pInterface,
+ void *pvUser,
+ uint32_t cchReaderName,
+ uint32_t cbAtrLen)
{
AssertPtrReturn(pInterface, VERR_INVALID_PARAMETER);
LogFlowFunc(("ENTER: pvUser:%p, cchReaderName:%d, cbAtrLen:%d\n",
@@ -781,7 +773,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
{
case VRDE_SCARD_FN_ESTABLISHCONTEXT:
{
- Assert(cbData == sizeof(VRDESCARDESTABLISHCONTEXTRSP));
+ Assert(cbData == sizeof(VRDESCARDESTABLISHCONTEXTRSP) || RT_FAILURE(rcRequest));
VRDESCARDESTABLISHCONTEXTRSP *pRsp = (VRDESCARDESTABLISHCONTEXTRSP *)pvData;
UCRREMOTE *pRemote = (UCRREMOTE *)pvUser;
@@ -805,7 +797,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_LISTREADERS:
{
- Assert(cbData == sizeof(VRDESCARDLISTREADERSRSP));
+ Assert(cbData == sizeof(VRDESCARDLISTREADERSRSP) || RT_FAILURE(rcRequest));
VRDESCARDLISTREADERSRSP *pRsp = (VRDESCARDLISTREADERSRSP *)pvData;
UCRREMOTE *pRemote = (UCRREMOTE *)pvUser;
@@ -838,7 +830,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_RELEASECONTEXT:
{
- Assert(cbData == sizeof(VRDESCARDRELEASECONTEXTRSP));
+ Assert(cbData == sizeof(VRDESCARDRELEASECONTEXTRSP) || RT_FAILURE(rcRequest));
VRDESCARDRELEASECONTEXTRSP *pRsp = (VRDESCARDRELEASECONTEXTRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -852,7 +844,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_GETSTATUSCHANGE:
{
- Assert(cbData == sizeof(VRDESCARDGETSTATUSCHANGERSP));
+ Assert(cbData == sizeof(VRDESCARDGETSTATUSCHANGERSP) || RT_FAILURE(rcRequest));
VRDESCARDGETSTATUSCHANGERSP *pRsp = (VRDESCARDGETSTATUSCHANGERSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -861,7 +853,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
LogFlowFunc(("GETSTATUSCHANGE\n"));
uint32_t rcCard;
- if (RT_FAILURE(rc))
+ if (RT_FAILURE(rcRequest))
{
rcCard = VRDE_SCARD_E_NO_SMARTCARD;
}
@@ -910,7 +902,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_CANCEL:
{
- Assert(cbData == sizeof(VRDESCARDCANCELRSP));
+ Assert(cbData == sizeof(VRDESCARDCANCELRSP) || RT_FAILURE(rcRequest));
VRDESCARDCANCELRSP *pRsp = (VRDESCARDCANCELRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -921,7 +913,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_CONNECT:
{
- Assert(cbData == sizeof(VRDESCARDCONNECTRSP));
+ Assert(cbData == sizeof(VRDESCARDCONNECTRSP) || RT_FAILURE(rcRequest));
VRDESCARDCONNECTRSP *pRsp = (VRDESCARDCONNECTRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -932,7 +924,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
uint32_t u32ActiveProtocol = 0;
uint32_t rcCard;
- if (RT_FAILURE(rc))
+ if (RT_FAILURE(rcRequest))
{
rcCard = VRDE_SCARD_E_NO_SMARTCARD;
}
@@ -960,7 +952,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_RECONNECT:
{
- Assert(cbData == sizeof(VRDESCARDRECONNECTRSP));
+ Assert(cbData == sizeof(VRDESCARDRECONNECTRSP) || RT_FAILURE(rcRequest));
VRDESCARDRECONNECTRSP *pRsp = (VRDESCARDRECONNECTRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -971,7 +963,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_DISCONNECT:
{
- Assert(cbData == sizeof(VRDESCARDDISCONNECTRSP));
+ Assert(cbData == sizeof(VRDESCARDDISCONNECTRSP) || RT_FAILURE(rcRequest));
VRDESCARDDISCONNECTRSP *pRsp = (VRDESCARDDISCONNECTRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -983,7 +975,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
uint32_t rcCard;
- if (RT_FAILURE(rc))
+ if (RT_FAILURE(rcRequest))
{
rcCard = VRDE_SCARD_E_NO_SMARTCARD;
}
@@ -1001,7 +993,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_BEGINTRANSACTION:
{
- Assert(cbData == sizeof(VRDESCARDBEGINTRANSACTIONRSP));
+ Assert(cbData == sizeof(VRDESCARDBEGINTRANSACTIONRSP) || RT_FAILURE(rcRequest));
VRDESCARDBEGINTRANSACTIONRSP *pRsp = (VRDESCARDBEGINTRANSACTIONRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -1012,7 +1004,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_ENDTRANSACTION:
{
- Assert(cbData == sizeof(VRDESCARDENDTRANSACTIONRSP));
+ Assert(cbData == sizeof(VRDESCARDENDTRANSACTIONRSP) || RT_FAILURE(rcRequest));
VRDESCARDENDTRANSACTIONRSP *pRsp = (VRDESCARDENDTRANSACTIONRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -1023,7 +1015,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_STATE:
{
- Assert(cbData == sizeof(VRDESCARDSTATERSP));
+ Assert(cbData == sizeof(VRDESCARDSTATERSP) || RT_FAILURE(rcRequest));
VRDESCARDSTATERSP *pRsp = (VRDESCARDSTATERSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -1034,7 +1026,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_STATUS:
{
- Assert(cbData == sizeof(VRDESCARDSTATUSRSP));
+ Assert(cbData == sizeof(VRDESCARDSTATUSRSP) || RT_FAILURE(rcRequest));
VRDESCARDSTATUSRSP *pRsp = (VRDESCARDSTATUSRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -1051,7 +1043,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
uint32_t rcCard;
- if (RT_FAILURE(rc))
+ if (RT_FAILURE(rcRequest))
{
rcCard = VRDE_SCARD_E_NO_SMARTCARD;
}
@@ -1085,7 +1077,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_TRANSMIT:
{
- Assert(cbData == sizeof(VRDESCARDTRANSMITRSP));
+ Assert(cbData == sizeof(VRDESCARDTRANSMITRSP) || RT_FAILURE(rcRequest));
VRDESCARDTRANSMITRSP *pRsp = (VRDESCARDTRANSMITRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -1099,7 +1091,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
uint32_t rcCard;
- if (RT_FAILURE(rc))
+ if (RT_FAILURE(rcRequest))
{
rcCard = VRDE_SCARD_E_NO_SMARTCARD;
}
@@ -1129,7 +1121,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_CONTROL:
{
- Assert(cbData == sizeof(VRDESCARDCONTROLRSP));
+ Assert(cbData == sizeof(VRDESCARDCONTROLRSP) || RT_FAILURE(rcRequest));
VRDESCARDCONTROLRSP *pRsp = (VRDESCARDCONTROLRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -1142,7 +1134,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
uint32_t rcCard;
- if (RT_FAILURE(rc))
+ if (RT_FAILURE(rcRequest))
{
rcCard = VRDE_SCARD_E_NO_SMARTCARD;
}
@@ -1169,7 +1161,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_GETATTRIB:
{
- Assert(cbData == sizeof(VRDESCARDGETATTRIBRSP));
+ Assert(cbData == sizeof(VRDESCARDGETATTRIBRSP) || RT_FAILURE(rcRequest));
VRDESCARDGETATTRIBRSP *pRsp = (VRDESCARDGETATTRIBRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -1182,7 +1174,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
uint32_t rcCard;
- if (RT_FAILURE(rc))
+ if (RT_FAILURE(rcRequest))
{
rcCard = VRDE_SCARD_E_NO_SMARTCARD;
}
@@ -1209,7 +1201,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
case VRDE_SCARD_FN_SETATTRIB:
{
- Assert(cbData == sizeof(VRDESCARDSETATTRIBRSP));
+ Assert(cbData == sizeof(VRDESCARDSETATTRIBRSP) || RT_FAILURE(rcRequest));
VRDESCARDSETATTRIBRSP *pRsp = (VRDESCARDSETATTRIBRSP *)pvData;
UCRREQCTX *pCtx = (UCRREQCTX *)pvUser;
@@ -1219,7 +1211,7 @@ int UsbCardReader::VRDEResponse(int rcRequest, void *pvUser, uint32_t u32Functio
uint32_t rcCard;
- if (RT_FAILURE(rc))
+ if (RT_FAILURE(rcRequest))
{
rcCard = VRDE_SCARD_E_NO_SMARTCARD;
}
@@ -1834,7 +1826,7 @@ int UsbCardReader::SetAttrib(struct USBCARDREADER *pDrv,
* PDM
*/
-/* static */ DECLCALLBACK(void *)UsbCardReader::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
+/* static */ DECLCALLBACK(void *) UsbCardReader::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
LogFlowFunc(("pInterface:%p, pszIID:%s\n", pInterface, pszIID));
PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
diff --git a/src/VBox/Main/src-client/VBoxDriversRegister.cpp b/src/VBox/Main/src-client/VBoxDriversRegister.cpp
index 26a89c6af..b98babe24 100644
--- a/src/VBox/Main/src-client/VBoxDriversRegister.cpp
+++ b/src/VBox/Main/src-client/VBoxDriversRegister.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -24,6 +24,7 @@
#include "DisplayImpl.h"
#include "VMMDev.h"
#include "AudioSnifferInterface.h"
+#include "Nvram.h"
#ifdef VBOX_WITH_USB_VIDEO
# include "UsbWebcamInterface.h"
#endif
@@ -32,7 +33,7 @@
#endif
#include "ConsoleImpl.h"
#ifdef VBOX_WITH_PCI_PASSTHROUGH
-# include "PciRawDevImpl.h"
+# include "PCIRawDevImpl.h"
#endif
#include "Logging.h"
@@ -72,6 +73,10 @@ extern "C" DECLEXPORT(int) VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_
if (RT_FAILURE(rc))
return rc;
+ rc = pCallbacks->pfnRegister(pCallbacks, &Nvram::DrvReg);
+ if (RT_FAILURE(rc))
+ return rc;
+
#ifdef VBOX_WITH_USB_VIDEO
rc = pCallbacks->pfnRegister(pCallbacks, &UsbWebcamInterface::DrvReg);
if (RT_FAILURE(rc))
@@ -89,7 +94,7 @@ extern "C" DECLEXPORT(int) VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_
return rc;
#ifdef VBOX_WITH_PCI_PASSTHROUGH
- rc = pCallbacks->pfnRegister(pCallbacks, &PciRawDev::DrvReg);
+ rc = pCallbacks->pfnRegister(pCallbacks, &PCIRawDev::DrvReg);
if (RT_FAILURE(rc))
return rc;
#endif
diff --git a/src/VBox/Main/src-client/VMMDevInterface.cpp b/src/VBox/Main/src-client/VMMDevInterface.cpp
index 813179cb9..5c3809fe7 100644
--- a/src/VBox/Main/src-client/VMMDevInterface.cpp
+++ b/src/VBox/Main/src-client/VMMDevInterface.cpp
@@ -115,7 +115,8 @@ VMMDev::~VMMDev()
PPDMIVMMDEVPORT VMMDev::getVMMDevPort()
{
- AssertReturn(mpDrv, NULL);
+ if (!mpDrv)
+ return NULL;
return mpDrv->pUpPort;
}
diff --git a/src/VBox/Main/src-client/win/dllmain.cpp b/src/VBox/Main/src-client/win/dllmain.cpp
index 7d0e8c85f..db1181cb5 100644
--- a/src/VBox/Main/src-client/win/dllmain.cpp
+++ b/src/VBox/Main/src-client/win/dllmain.cpp
@@ -45,7 +45,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
DisableThreadLibraryCalls(hInstance);
// idempotent, so doesn't harm, and needed for COM embedding scenario
- RTR3Init();
+ RTR3InitDll(0);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
diff --git a/src/VBox/Main/src-client/xpcom/module.cpp b/src/VBox/Main/src-client/xpcom/module.cpp
index e810229ce..e646a3bdb 100644
--- a/src/VBox/Main/src-client/xpcom/module.cpp
+++ b/src/VBox/Main/src-client/xpcom/module.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2009 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -36,7 +36,13 @@
# include "ExtPackManagerImpl.h"
#endif
#include "GuestImpl.h"
-#include "GuestDirEntryImpl.h"
+#ifdef VBOX_WITH_GUEST_CONTROL
+# include "GuestDirectoryImpl.h"
+# include "GuestFileImpl.h"
+# include "GuestFsObjInfoImpl.h"
+# include "GuestProcessImpl.h"
+# include "GuestSessionImpl.h"
+#endif
#include "KeyboardImpl.h"
#include "MachineDebuggerImpl.h"
#include "MouseImpl.h"
@@ -56,8 +62,18 @@
NS_DECL_CLASSINFO(Guest)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(Guest, IGuest)
-NS_DECL_CLASSINFO(GuestDirEntry)
-NS_IMPL_THREADSAFE_ISUPPORTS1_CI(GuestDirEntry, IGuestDirEntry)
+#ifdef VBOX_WITH_GUEST_CONTROL
+NS_DECL_CLASSINFO(GuestDirectory)
+NS_IMPL_THREADSAFE_ISUPPORTS2_CI(GuestDirectory, IGuestDirectory, IDirectory)
+NS_DECL_CLASSINFO(GuestFile)
+NS_IMPL_THREADSAFE_ISUPPORTS2_CI(GuestFile, IGuestFile, IFile)
+NS_DECL_CLASSINFO(GuestFsObjInfo)
+NS_IMPL_THREADSAFE_ISUPPORTS2_CI(GuestFsObjInfo, IGuestFsObjInfo, IFsObjInfo)
+NS_DECL_CLASSINFO(GuestProcess)
+NS_IMPL_THREADSAFE_ISUPPORTS2_CI(GuestProcess, IGuestProcess, IProcess)
+NS_DECL_CLASSINFO(GuestSession)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(GuestSession, IGuestSession)
+#endif
NS_DECL_CLASSINFO(Keyboard)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(Keyboard, IKeyboard)
NS_DECL_CLASSINFO(Mouse)
@@ -73,16 +89,16 @@ NS_IMPL_THREADSAFE_ISUPPORTS1_CI(CombinedProgress, IProgress)
NS_DECL_CLASSINFO(OUSBDevice)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(OUSBDevice, IUSBDevice)
NS_DECL_CLASSINFO(RemoteUSBDevice)
-NS_IMPL_THREADSAFE_ISUPPORTS1_CI(RemoteUSBDevice, IHostUSBDevice)
+NS_IMPL_THREADSAFE_ISUPPORTS2_CI(RemoteUSBDevice, IHostUSBDevice, IUSBDevice)
NS_DECL_CLASSINFO(SharedFolder)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(SharedFolder, ISharedFolder)
NS_DECL_CLASSINFO(VRDEServerInfo)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(VRDEServerInfo, IVRDEServerInfo)
#ifdef VBOX_WITH_EXTPACK
NS_DECL_CLASSINFO(ExtPackFile)
-NS_IMPL_THREADSAFE_ISUPPORTS1_CI(ExtPackFile, IExtPackFile)
+NS_IMPL_THREADSAFE_ISUPPORTS2_CI(ExtPackFile, IExtPackFile, IExtPackBase)
NS_DECL_CLASSINFO(ExtPack)
-NS_IMPL_THREADSAFE_ISUPPORTS1_CI(ExtPack, IExtPack)
+NS_IMPL_THREADSAFE_ISUPPORTS2_CI(ExtPack, IExtPack, IExtPackBase)
NS_DECL_CLASSINFO(ExtPackManager)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(ExtPackManager, IExtPackManager)
#endif
diff --git a/src/VBox/Main/src-helper-apps/VBoxExtPackHelperApp.cpp b/src/VBox/Main/src-helper-apps/VBoxExtPackHelperApp.cpp
index 1bc168858..6929eb7e0 100644
--- a/src/VBox/Main/src-helper-apps/VBoxExtPackHelperApp.cpp
+++ b/src/VBox/Main/src-helper-apps/VBoxExtPackHelperApp.cpp
@@ -356,7 +356,7 @@ static RTEXITCODE UnpackExtPackDir(const char *pszDstDirName, RTVFSOBJ hVfsObj)
return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTVfsObjQueryInfo failed on '%s': %Rrc", pszDstDirName, rc);
ObjInfo.Attr.fMode &= ~(RTFS_UNIX_IWOTH | RTFS_UNIX_IWGRP);
- rc = RTDirCreate(pszDstDirName, ObjInfo.Attr.fMode);
+ rc = RTDirCreate(pszDstDirName, ObjInfo.Attr.fMode, 0);
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to create directory '%s': %Rrc", pszDstDirName, rc);
@@ -566,7 +566,7 @@ static RTEXITCODE UnpackExtPack(RTFILE hTarballFile, const char *pszDirDst, RTMA
rc = RTManifestEqualsEx(hUnpackManifest, hValidManifest, NULL /*papszIgnoreEntries*/, NULL /*papszIgnoreAttr*/,
0 /*fFlags*/, szError, sizeof(szError));
if (RT_SUCCESS(rc))
- rc = RTEXITCODE_SUCCESS;
+ rcExit = RTEXITCODE_SUCCESS;
else if (rc == VERR_NOT_EQUAL && szError[0])
rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Manifest mismatch: %s", szError);
else
@@ -707,7 +707,7 @@ static RTEXITCODE DoInstall2(const char *pszBaseDir, const char *pszCertDir, con
* Create the temporary directory and prepare the extension pack within it.
* If all checks out correctly, rename it to the final directory.
*/
- RTDirCreate(pszBaseDir, 0755);
+ RTDirCreate(pszBaseDir, 0755, 0);
#ifndef RT_OS_WINDOWS
/*
* Because of umask, we have to apply the mode again.
@@ -718,7 +718,7 @@ static RTEXITCODE DoInstall2(const char *pszBaseDir, const char *pszCertDir, con
#else
/** @todo Ownership tricks on windows? */
#endif
- rc = RTDirCreate(szTmpPath, 0700);
+ rc = RTDirCreate(szTmpPath, 0700, 0);
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to create temporary directory: %Rrc ('%s')", rc, szTmpPath);
@@ -1569,7 +1569,7 @@ static RTEXITCODE RelaunchElevated(int argc, char **argv, int iCmd, const char *
rc = RTPathAppend(szTempDir, sizeof(szTempDir), "VBoxExtPackHelper-XXXXXX");
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathAppend failed: %Rrc", rc);
- rc = RTDirCreateTemp(szTempDir);
+ rc = RTDirCreateTemp(szTempDir, 0700);
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDirCreateTemp failed: %Rrc", rc);
@@ -1767,7 +1767,7 @@ int main(int argc, char **argv)
/*
* Initialize IPRT and check that we're correctly installed.
*/
- int rc = RTR3Init();
+ int rc = RTR3InitExe(argc, &argv, 0);
if (RT_FAILURE(rc))
return RTMsgInitFailure(rc);
@@ -1906,7 +1906,7 @@ extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPST
g_hInstance = hInstance;
NOREF(hPrevInstance); NOREF(nShowCmd); NOREF(lpCmdLine);
- int rc = RTR3Init();
+ int rc = RTR3InitExeNoArguments(0);
if (RT_FAILURE(rc))
return RTMsgInitFailure(rc);
diff --git a/src/VBox/Main/src-server/ApplianceImpl.cpp b/src/VBox/Main/src-server/ApplianceImpl.cpp
index 4edfff352..05fc3b675 100644
--- a/src/VBox/Main/src-server/ApplianceImpl.cpp
+++ b/src/VBox/Main/src-server/ApplianceImpl.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2008-2011 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -25,6 +25,7 @@
#include "VFSExplorerImpl.h"
#include "VirtualBoxImpl.h"
#include "GuestOSTypeImpl.h"
+#include "Global.h"
#include "ProgressImpl.h"
#include "MachineImpl.h"
@@ -44,99 +45,99 @@ using namespace std;
static const struct
{
ovf::CIMOSType_T cim;
- const char *pcszVbox;
+ VBOXOSTYPE osType;
}
g_osTypes[] =
{
- { ovf::CIMOSType_CIMOS_Unknown, SchemaDefs_OSTypeId_Other },
- { ovf::CIMOSType_CIMOS_OS2, SchemaDefs_OSTypeId_OS2 },
- { ovf::CIMOSType_CIMOS_OS2, SchemaDefs_OSTypeId_OS2Warp3 },
- { ovf::CIMOSType_CIMOS_OS2, SchemaDefs_OSTypeId_OS2Warp4 },
- { ovf::CIMOSType_CIMOS_OS2, SchemaDefs_OSTypeId_OS2Warp45 },
- { ovf::CIMOSType_CIMOS_MSDOS, SchemaDefs_OSTypeId_DOS },
- { ovf::CIMOSType_CIMOS_WIN3x, SchemaDefs_OSTypeId_Windows31 },
- { ovf::CIMOSType_CIMOS_WIN95, SchemaDefs_OSTypeId_Windows95 },
- { ovf::CIMOSType_CIMOS_WIN98, SchemaDefs_OSTypeId_Windows98 },
- { ovf::CIMOSType_CIMOS_WINNT, SchemaDefs_OSTypeId_WindowsNT },
- { ovf::CIMOSType_CIMOS_WINNT, SchemaDefs_OSTypeId_WindowsNT4 },
- { ovf::CIMOSType_CIMOS_NetWare, SchemaDefs_OSTypeId_Netware },
- { ovf::CIMOSType_CIMOS_NovellOES, SchemaDefs_OSTypeId_Netware },
- { ovf::CIMOSType_CIMOS_Solaris, SchemaDefs_OSTypeId_Solaris },
- { ovf::CIMOSType_CIMOS_SunOS, SchemaDefs_OSTypeId_Solaris },
- { ovf::CIMOSType_CIMOS_FreeBSD, SchemaDefs_OSTypeId_FreeBSD },
- { ovf::CIMOSType_CIMOS_NetBSD, SchemaDefs_OSTypeId_NetBSD },
- { ovf::CIMOSType_CIMOS_QNX, SchemaDefs_OSTypeId_QNX },
- { ovf::CIMOSType_CIMOS_Windows2000, SchemaDefs_OSTypeId_Windows2000 },
- { ovf::CIMOSType_CIMOS_WindowsMe, SchemaDefs_OSTypeId_WindowsMe },
- { ovf::CIMOSType_CIMOS_OpenBSD, SchemaDefs_OSTypeId_OpenBSD },
- { ovf::CIMOSType_CIMOS_WindowsXP, SchemaDefs_OSTypeId_WindowsXP },
- { ovf::CIMOSType_CIMOS_WindowsXPEmbedded, SchemaDefs_OSTypeId_WindowsXP },
- { ovf::CIMOSType_CIMOS_WindowsEmbeddedforPointofService, SchemaDefs_OSTypeId_WindowsXP },
- { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2003, SchemaDefs_OSTypeId_Windows2003 },
- { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2003_64, SchemaDefs_OSTypeId_Windows2003_64 },
- { ovf::CIMOSType_CIMOS_WindowsXP_64, SchemaDefs_OSTypeId_WindowsXP_64 },
- { ovf::CIMOSType_CIMOS_WindowsVista, SchemaDefs_OSTypeId_WindowsVista },
- { ovf::CIMOSType_CIMOS_WindowsVista_64, SchemaDefs_OSTypeId_WindowsVista_64 },
- { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2008, SchemaDefs_OSTypeId_Windows2008 },
- { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2008_64, SchemaDefs_OSTypeId_Windows2008_64 },
- { ovf::CIMOSType_CIMOS_FreeBSD_64, SchemaDefs_OSTypeId_FreeBSD_64 },
- { ovf::CIMOSType_CIMOS_MACOS, SchemaDefs_OSTypeId_MacOS },
- { ovf::CIMOSType_CIMOS_MACOS, SchemaDefs_OSTypeId_MacOS_64 }, // there is no CIM 64-bit type for this
+ { ovf::CIMOSType_CIMOS_Unknown, VBOXOSTYPE_Unknown },
+ { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS2 },
+ { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS2Warp3 },
+ { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS2Warp4 },
+ { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS2Warp45 },
+ { ovf::CIMOSType_CIMOS_MSDOS, VBOXOSTYPE_DOS },
+ { ovf::CIMOSType_CIMOS_WIN3x, VBOXOSTYPE_Win31 },
+ { ovf::CIMOSType_CIMOS_WIN95, VBOXOSTYPE_Win95 },
+ { ovf::CIMOSType_CIMOS_WIN98, VBOXOSTYPE_Win98 },
+ { ovf::CIMOSType_CIMOS_WINNT, VBOXOSTYPE_WinNT },
+ { ovf::CIMOSType_CIMOS_WINNT, VBOXOSTYPE_WinNT4 },
+ { ovf::CIMOSType_CIMOS_NetWare, VBOXOSTYPE_Netware },
+ { ovf::CIMOSType_CIMOS_NovellOES, VBOXOSTYPE_Netware },
+ { ovf::CIMOSType_CIMOS_Solaris, VBOXOSTYPE_Solaris },
+ { ovf::CIMOSType_CIMOS_SunOS, VBOXOSTYPE_Solaris },
+ { ovf::CIMOSType_CIMOS_FreeBSD, VBOXOSTYPE_FreeBSD },
+ { ovf::CIMOSType_CIMOS_NetBSD, VBOXOSTYPE_NetBSD },
+ { ovf::CIMOSType_CIMOS_QNX, VBOXOSTYPE_QNX },
+ { ovf::CIMOSType_CIMOS_Windows2000, VBOXOSTYPE_Win2k },
+ { ovf::CIMOSType_CIMOS_WindowsMe, VBOXOSTYPE_WinMe },
+ { ovf::CIMOSType_CIMOS_OpenBSD, VBOXOSTYPE_OpenBSD },
+ { ovf::CIMOSType_CIMOS_WindowsXP, VBOXOSTYPE_WinXP },
+ { ovf::CIMOSType_CIMOS_WindowsXPEmbedded, VBOXOSTYPE_WinXP },
+ { ovf::CIMOSType_CIMOS_WindowsEmbeddedforPointofService, VBOXOSTYPE_WinXP },
+ { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2003, VBOXOSTYPE_Win2k3 },
+ { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2003_64, VBOXOSTYPE_Win2k3_x64 },
+ { ovf::CIMOSType_CIMOS_WindowsXP_64, VBOXOSTYPE_WinXP_x64 },
+ { ovf::CIMOSType_CIMOS_WindowsVista, VBOXOSTYPE_WinVista },
+ { ovf::CIMOSType_CIMOS_WindowsVista_64, VBOXOSTYPE_WinVista_x64 },
+ { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2008, VBOXOSTYPE_Win2k8 },
+ { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2008_64, VBOXOSTYPE_Win2k8_x64 },
+ { ovf::CIMOSType_CIMOS_FreeBSD_64, VBOXOSTYPE_FreeBSD_x64 },
+ { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS },
+ { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS_x64 }, // there is no CIM 64-bit type for this
// Linuxes
- { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux, SchemaDefs_OSTypeId_RedHat },
- { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, SchemaDefs_OSTypeId_RedHat_64 },
- { ovf::CIMOSType_CIMOS_Solaris_64, SchemaDefs_OSTypeId_Solaris_64 },
- { ovf::CIMOSType_CIMOS_SUSE, SchemaDefs_OSTypeId_OpenSUSE },
- { ovf::CIMOSType_CIMOS_SLES, SchemaDefs_OSTypeId_OpenSUSE },
- { ovf::CIMOSType_CIMOS_NovellLinuxDesktop, SchemaDefs_OSTypeId_OpenSUSE },
- { ovf::CIMOSType_CIMOS_SUSE_64, SchemaDefs_OSTypeId_OpenSUSE_64 },
- { ovf::CIMOSType_CIMOS_SLES_64, SchemaDefs_OSTypeId_OpenSUSE_64 },
- { ovf::CIMOSType_CIMOS_LINUX, SchemaDefs_OSTypeId_Linux },
- { ovf::CIMOSType_CIMOS_LINUX, SchemaDefs_OSTypeId_Linux22 },
- { ovf::CIMOSType_CIMOS_SunJavaDesktopSystem, SchemaDefs_OSTypeId_Linux },
- { ovf::CIMOSType_CIMOS_TurboLinux, SchemaDefs_OSTypeId_Turbolinux },
- { ovf::CIMOSType_CIMOS_TurboLinux_64, SchemaDefs_OSTypeId_Turbolinux_64 },
- { ovf::CIMOSType_CIMOS_Mandriva, SchemaDefs_OSTypeId_Mandriva },
- { ovf::CIMOSType_CIMOS_Mandriva_64, SchemaDefs_OSTypeId_Mandriva_64 },
- { ovf::CIMOSType_CIMOS_Ubuntu, SchemaDefs_OSTypeId_Ubuntu },
- { ovf::CIMOSType_CIMOS_Ubuntu_64, SchemaDefs_OSTypeId_Ubuntu_64 },
- { ovf::CIMOSType_CIMOS_Debian, SchemaDefs_OSTypeId_Debian },
- { ovf::CIMOSType_CIMOS_Debian_64, SchemaDefs_OSTypeId_Debian_64 },
- { ovf::CIMOSType_CIMOS_Linux_2_4_x, SchemaDefs_OSTypeId_Linux24 },
- { ovf::CIMOSType_CIMOS_Linux_2_4_x_64, SchemaDefs_OSTypeId_Linux24_64 },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x, SchemaDefs_OSTypeId_Linux26 },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, SchemaDefs_OSTypeId_Linux26_64 },
- { ovf::CIMOSType_CIMOS_Linux_64, SchemaDefs_OSTypeId_Linux26_64 },
+ { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux, VBOXOSTYPE_RedHat },
+ { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, VBOXOSTYPE_RedHat_x64 },
+ { ovf::CIMOSType_CIMOS_Solaris_64, VBOXOSTYPE_Solaris_x64 },
+ { ovf::CIMOSType_CIMOS_SUSE, VBOXOSTYPE_OpenSUSE },
+ { ovf::CIMOSType_CIMOS_SLES, VBOXOSTYPE_OpenSUSE },
+ { ovf::CIMOSType_CIMOS_NovellLinuxDesktop, VBOXOSTYPE_OpenSUSE },
+ { ovf::CIMOSType_CIMOS_SUSE_64, VBOXOSTYPE_OpenSUSE_x64 },
+ { ovf::CIMOSType_CIMOS_SLES_64, VBOXOSTYPE_OpenSUSE_x64 },
+ { ovf::CIMOSType_CIMOS_LINUX, VBOXOSTYPE_Linux },
+ { ovf::CIMOSType_CIMOS_LINUX, VBOXOSTYPE_Linux22 },
+ { ovf::CIMOSType_CIMOS_SunJavaDesktopSystem, VBOXOSTYPE_Linux },
+ { ovf::CIMOSType_CIMOS_TurboLinux, VBOXOSTYPE_Turbolinux },
+ { ovf::CIMOSType_CIMOS_TurboLinux_64, VBOXOSTYPE_Turbolinux_x64 },
+ { ovf::CIMOSType_CIMOS_Mandriva, VBOXOSTYPE_Mandriva },
+ { ovf::CIMOSType_CIMOS_Mandriva_64, VBOXOSTYPE_Mandriva_x64 },
+ { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu },
+ { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu_x64 },
+ { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian },
+ { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian_x64 },
+ { ovf::CIMOSType_CIMOS_Linux_2_4_x, VBOXOSTYPE_Linux24 },
+ { ovf::CIMOSType_CIMOS_Linux_2_4_x_64, VBOXOSTYPE_Linux24_x64 },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_Linux26 },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_Linux26_x64 },
+ { ovf::CIMOSType_CIMOS_Linux_64, VBOXOSTYPE_Linux26_x64 },
// types that we have support for but CIM doesn't
- { ovf::CIMOSType_CIMOS_Linux_2_6_x, SchemaDefs_OSTypeId_ArchLinux },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, SchemaDefs_OSTypeId_ArchLinux_64 },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x, SchemaDefs_OSTypeId_Fedora },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, SchemaDefs_OSTypeId_Fedora_64 },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x, SchemaDefs_OSTypeId_Gentoo },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, SchemaDefs_OSTypeId_Gentoo_64 },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x, SchemaDefs_OSTypeId_Xandros },
- { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, SchemaDefs_OSTypeId_Xandros_64 },
- { ovf::CIMOSType_CIMOS_Solaris, SchemaDefs_OSTypeId_OpenSolaris },
- { ovf::CIMOSType_CIMOS_Solaris_64, SchemaDefs_OSTypeId_OpenSolaris_64 },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_ArchLinux },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_ArchLinux_x64 },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_FedoraCore },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_FedoraCore_x64 },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_Gentoo },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_Gentoo_x64 },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_Xandros },
+ { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_Xandros_x64 },
+ { ovf::CIMOSType_CIMOS_Solaris, VBOXOSTYPE_OpenSolaris },
+ { ovf::CIMOSType_CIMOS_Solaris_64, VBOXOSTYPE_OpenSolaris_x64 },
// types added with CIM 2.25.0 follow:
- { ovf::CIMOSType_CIMOS_WindowsServer2008R2, SchemaDefs_OSTypeId_Windows2008 }, // duplicate, see above
-// { ovf::CIMOSType_CIMOS_VMwareESXi = 104, // we can't run ESX in a VM
- { ovf::CIMOSType_CIMOS_Windows7, SchemaDefs_OSTypeId_Windows7 },
- { ovf::CIMOSType_CIMOS_Windows7, SchemaDefs_OSTypeId_Windows7_64 }, // there is no CIM 64-bit type for this
- { ovf::CIMOSType_CIMOS_CentOS, SchemaDefs_OSTypeId_RedHat },
- { ovf::CIMOSType_CIMOS_CentOS_64, SchemaDefs_OSTypeId_RedHat_64 },
- { ovf::CIMOSType_CIMOS_OracleEnterpriseLinux, SchemaDefs_OSTypeId_Oracle },
- { ovf::CIMOSType_CIMOS_OracleEnterpriseLinux_64, SchemaDefs_OSTypeId_Oracle_64 },
- { ovf::CIMOSType_CIMOS_eComStation, SchemaDefs_OSTypeId_OS2eCS }
+ { ovf::CIMOSType_CIMOS_WindowsServer2008R2, VBOXOSTYPE_Win2k8 }, // duplicate, see above
+// { ovf::CIMOSType_CIMOS_VMwareESXi = 104, // we can't run ESX in a VM
+ { ovf::CIMOSType_CIMOS_Windows7, VBOXOSTYPE_Win7 },
+ { ovf::CIMOSType_CIMOS_Windows7, VBOXOSTYPE_Win7_x64 }, // there is no CIM 64-bit type for this
+ { ovf::CIMOSType_CIMOS_CentOS, VBOXOSTYPE_RedHat },
+ { ovf::CIMOSType_CIMOS_CentOS_64, VBOXOSTYPE_RedHat_x64 },
+ { ovf::CIMOSType_CIMOS_OracleEnterpriseLinux, VBOXOSTYPE_Oracle },
+ { ovf::CIMOSType_CIMOS_OracleEnterpriseLinux_64, VBOXOSTYPE_Oracle_x64 },
+ { ovf::CIMOSType_CIMOS_eComStation, VBOXOSTYPE_ECS }
// there are no CIM types for these, so these turn to "other" on export:
- // SchemaDefs_OSTypeId_OpenBSD
- // SchemaDefs_OSTypeId_OpenBSD_64
- // SchemaDefs_OSTypeId_NetBSD
- // SchemaDefs_OSTypeId_NetBSD_64
+ // VBOXOSTYPE_OpenBSD
+ // VBOXOSTYPE_OpenBSD_x64
+ // VBOXOSTYPE_NetBSD
+ // VBOXOSTYPE_NetBSD_x64
};
@@ -144,59 +145,59 @@ g_osTypes[] =
struct osTypePattern
{
const char *pcszPattern;
- const char *pcszVbox;
+ VBOXOSTYPE osType;
};
/* These are the 32-Bit ones. They are sorted by priority. */
static const osTypePattern g_osTypesPattern[] =
{
- {"Windows NT", SchemaDefs_OSTypeId_WindowsNT4},
- {"Windows XP", SchemaDefs_OSTypeId_WindowsXP},
- {"Windows 2000", SchemaDefs_OSTypeId_Windows2000},
- {"Windows 2003", SchemaDefs_OSTypeId_Windows2003},
- {"Windows Vista", SchemaDefs_OSTypeId_WindowsVista},
- {"Windows 2008", SchemaDefs_OSTypeId_Windows2008},
- {"SUSE", SchemaDefs_OSTypeId_OpenSUSE},
- {"Novell", SchemaDefs_OSTypeId_OpenSUSE},
- {"Red Hat", SchemaDefs_OSTypeId_RedHat},
- {"Mandriva", SchemaDefs_OSTypeId_Mandriva},
- {"Ubuntu", SchemaDefs_OSTypeId_Ubuntu},
- {"Debian", SchemaDefs_OSTypeId_Debian},
- {"QNX", SchemaDefs_OSTypeId_QNX},
- {"Linux 2.4", SchemaDefs_OSTypeId_Linux24},
- {"Linux 2.6", SchemaDefs_OSTypeId_Linux26},
- {"Linux", SchemaDefs_OSTypeId_Linux},
- {"OpenSolaris", SchemaDefs_OSTypeId_OpenSolaris},
- {"Solaris", SchemaDefs_OSTypeId_OpenSolaris},
- {"FreeBSD", SchemaDefs_OSTypeId_FreeBSD},
- {"NetBSD", SchemaDefs_OSTypeId_NetBSD},
- {"Windows 95", SchemaDefs_OSTypeId_Windows95},
- {"Windows 98", SchemaDefs_OSTypeId_Windows98},
- {"Windows Me", SchemaDefs_OSTypeId_WindowsMe},
- {"Windows 3.", SchemaDefs_OSTypeId_Windows31},
- {"DOS", SchemaDefs_OSTypeId_DOS},
- {"OS2", SchemaDefs_OSTypeId_OS2}
+ {"Windows NT", VBOXOSTYPE_WinNT4},
+ {"Windows XP", VBOXOSTYPE_WinXP},
+ {"Windows 2000", VBOXOSTYPE_Win2k},
+ {"Windows 2003", VBOXOSTYPE_Win2k3},
+ {"Windows Vista", VBOXOSTYPE_WinVista},
+ {"Windows 2008", VBOXOSTYPE_Win2k8},
+ {"SUSE", VBOXOSTYPE_OpenSUSE},
+ {"Novell", VBOXOSTYPE_OpenSUSE},
+ {"Red Hat", VBOXOSTYPE_RedHat},
+ {"Mandriva", VBOXOSTYPE_Mandriva},
+ {"Ubuntu", VBOXOSTYPE_Ubuntu},
+ {"Debian", VBOXOSTYPE_Debian},
+ {"QNX", VBOXOSTYPE_QNX},
+ {"Linux 2.4", VBOXOSTYPE_Linux24},
+ {"Linux 2.6", VBOXOSTYPE_Linux26},
+ {"Linux", VBOXOSTYPE_Linux},
+ {"OpenSolaris", VBOXOSTYPE_OpenSolaris},
+ {"Solaris", VBOXOSTYPE_OpenSolaris},
+ {"FreeBSD", VBOXOSTYPE_FreeBSD},
+ {"NetBSD", VBOXOSTYPE_NetBSD},
+ {"Windows 95", VBOXOSTYPE_Win95},
+ {"Windows 98", VBOXOSTYPE_Win98},
+ {"Windows Me", VBOXOSTYPE_WinMe},
+ {"Windows 3.", VBOXOSTYPE_Win31},
+ {"DOS", VBOXOSTYPE_DOS},
+ {"OS2", VBOXOSTYPE_OS2}
};
/* These are the 64-Bit ones. They are sorted by priority. */
static const osTypePattern g_osTypesPattern64[] =
{
- {"Windows XP", SchemaDefs_OSTypeId_WindowsXP_64},
- {"Windows 2003", SchemaDefs_OSTypeId_Windows2003_64},
- {"Windows Vista", SchemaDefs_OSTypeId_WindowsVista_64},
- {"Windows 2008", SchemaDefs_OSTypeId_Windows2008_64},
- {"SUSE", SchemaDefs_OSTypeId_OpenSUSE_64},
- {"Novell", SchemaDefs_OSTypeId_OpenSUSE_64},
- {"Red Hat", SchemaDefs_OSTypeId_RedHat_64},
- {"Mandriva", SchemaDefs_OSTypeId_Mandriva_64},
- {"Ubuntu", SchemaDefs_OSTypeId_Ubuntu_64},
- {"Debian", SchemaDefs_OSTypeId_Debian_64},
- {"Linux 2.4", SchemaDefs_OSTypeId_Linux24_64},
- {"Linux 2.6", SchemaDefs_OSTypeId_Linux26_64},
- {"Linux", SchemaDefs_OSTypeId_Linux26_64},
- {"OpenSolaris", SchemaDefs_OSTypeId_OpenSolaris_64},
- {"Solaris", SchemaDefs_OSTypeId_OpenSolaris_64},
- {"FreeBSD", SchemaDefs_OSTypeId_FreeBSD_64},
+ {"Windows XP", VBOXOSTYPE_WinXP_x64},
+ {"Windows 2003", VBOXOSTYPE_Win2k3_x64},
+ {"Windows Vista", VBOXOSTYPE_WinVista_x64},
+ {"Windows 2008", VBOXOSTYPE_Win2k8_x64},
+ {"SUSE", VBOXOSTYPE_OpenSUSE_x64},
+ {"Novell", VBOXOSTYPE_OpenSUSE_x64},
+ {"Red Hat", VBOXOSTYPE_RedHat_x64},
+ {"Mandriva", VBOXOSTYPE_Mandriva_x64},
+ {"Ubuntu", VBOXOSTYPE_Ubuntu_x64},
+ {"Debian", VBOXOSTYPE_Debian_x64},
+ {"Linux 2.4", VBOXOSTYPE_Linux24_x64},
+ {"Linux 2.6", VBOXOSTYPE_Linux26_x64},
+ {"Linux", VBOXOSTYPE_Linux26_x64},
+ {"OpenSolaris", VBOXOSTYPE_OpenSolaris_x64},
+ {"Solaris", VBOXOSTYPE_OpenSolaris_x64},
+ {"FreeBSD", VBOXOSTYPE_FreeBSD_x64},
};
/**
@@ -214,7 +215,7 @@ void convertCIMOSType2VBoxOSType(Utf8Str &strType, ovf::CIMOSType_T c, const Utf
for (size_t i=0; i < RT_ELEMENTS(g_osTypesPattern); ++i)
if (cStr.contains (g_osTypesPattern[i].pcszPattern, Utf8Str::CaseInsensitive))
{
- strType = g_osTypesPattern[i].pcszVbox;
+ strType = Global::OSTypeId(g_osTypesPattern[i].osType);
return;
}
}
@@ -223,7 +224,7 @@ void convertCIMOSType2VBoxOSType(Utf8Str &strType, ovf::CIMOSType_T c, const Utf
for (size_t i=0; i < RT_ELEMENTS(g_osTypesPattern64); ++i)
if (cStr.contains (g_osTypesPattern64[i].pcszPattern, Utf8Str::CaseInsensitive))
{
- strType = g_osTypesPattern64[i].pcszVbox;
+ strType = Global::OSTypeId(g_osTypesPattern64[i].osType);
return;
}
}
@@ -232,12 +233,12 @@ void convertCIMOSType2VBoxOSType(Utf8Str &strType, ovf::CIMOSType_T c, const Utf
{
if (c == g_osTypes[i].cim)
{
- strType = g_osTypes[i].pcszVbox;
+ strType = Global::OSTypeId(g_osTypes[i].osType);
return;
}
}
- strType = SchemaDefs_OSTypeId_Other;
+ strType = Global::OSTypeId(VBOXOSTYPE_Unknown);
}
/**
@@ -250,7 +251,7 @@ ovf::CIMOSType_T convertVBoxOSType2CIMOSType(const char *pcszVbox)
{
for (size_t i = 0; i < RT_ELEMENTS(g_osTypes); ++i)
{
- if (!RTStrICmp(pcszVbox, g_osTypes[i].pcszVbox))
+ if (!RTStrICmp(pcszVbox, Global::OSTypeId(g_osTypes[i].osType)))
return g_osTypes[i].cim;
}
@@ -625,7 +626,7 @@ HRESULT Appliance::searchUniqueDiskImageFilePath(Utf8Str& aName) const
* already */
/** @todo: Maybe too cost-intensive; try to find a lighter way */
while ( RTPathExists(tmpName)
- || mVirtualBox->FindMedium(Bstr(tmpName).raw(), DeviceType_HardDisk, &harddisk) != VBOX_E_OBJECT_NOT_FOUND
+ || mVirtualBox->OpenMedium(Bstr(tmpName).raw(), DeviceType_HardDisk, AccessMode_ReadWrite, FALSE /* fForceNewUuid */, &harddisk) != VBOX_E_OBJECT_NOT_FOUND
)
{
RTStrFree(tmpName);
@@ -797,7 +798,8 @@ void Appliance::waitForAsyncProgress(ComObjPtr<Progress> &pProgressThis,
rc = pProgressThis->SetNextOperation(bstr.raw(), currentWeight);
if (FAILED(rc)) throw rc;
++cOp;
- }else
+ }
+ else
break;
}
diff --git a/src/VBox/Main/src-server/ApplianceImplExport.cpp b/src/VBox/Main/src-server/ApplianceImplExport.cpp
index 841356c4a..cc47b4d1c 100644
--- a/src/VBox/Main/src-server/ApplianceImplExport.cpp
+++ b/src/VBox/Main/src-server/ApplianceImplExport.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2008-2010 Oracle Corporation
+ * Copyright (C) 2008-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -33,6 +33,7 @@
#include "MachineImpl.h"
#include "MediumImpl.h"
#include "MediumFormatImpl.h"
+#include "Global.h"
#include "SystemPropertiesImpl.h"
#include "AutoCaller.h"
@@ -453,10 +454,9 @@ STDMETHODIMP Machine::Export(IAppliance *aAppliance, IN_BSTR location, IVirtualS
}
// <const name="NetworkAdapter" />
+ uint32_t maxNetworkAdapters = Global::getMaxNetworkAdapters(getChipsetType());
size_t a;
- for (a = 0;
- a < SchemaDefs::NetworkAdapterCount;
- ++a)
+ for (a = 0; a < maxNetworkAdapters; ++a)
{
ComPtr<INetworkAdapter> pNetworkAdapter;
BOOL fEnabled;
@@ -557,10 +557,15 @@ STDMETHODIMP Appliance::Write(IN_BSTR format, BOOL fManifest, IN_BSTR path, IPro
ovfF = OVF_0_9;
else if (strFormat == "ovf-1.0")
ovfF = OVF_1_0;
+ else if (strFormat == "ovf-2.0")
+ ovfF = OVF_2_0;
else
return setError(VBOX_E_FILE_ERROR,
tr("Invalid format \"%s\" specified"), strFormat.c_str());
+ /* as of OVF 2.0 we have to use SHA256 */
+ m->fSha256 = ovfF >= OVF_2_0;
+
ComObjPtr<Progress> progress;
HRESULT rc = S_OK;
try
@@ -657,7 +662,9 @@ void Appliance::buildXML(AutoWriteLockBase& writeLock,
{
xml::ElementNode *pelmRoot = doc.createRootElement("Envelope");
- pelmRoot->setAttribute("ovf:version", (enFormat == OVF_1_0) ? "1.0" : "0.9");
+ pelmRoot->setAttribute("ovf:version", enFormat == OVF_2_0 ? "2.0"
+ : enFormat == OVF_1_0 ? "1.0"
+ : "0.9");
pelmRoot->setAttribute("xml:lang", "en-US");
Utf8Str strNamespace = (enFormat == OVF_0_9)
@@ -787,7 +794,7 @@ void Appliance::buildXML(AutoWriteLockBase& writeLock,
ComPtr<IMedium> pSourceDisk;
Log(("Finding source disk \"%ls\"\n", bstrSrcFilePath.raw()));
- HRESULT rc = mVirtualBox->FindMedium(bstrSrcFilePath.raw(), DeviceType_HardDisk, pSourceDisk.asOutParam());
+ HRESULT rc = mVirtualBox->OpenMedium(bstrSrcFilePath.raw(), DeviceType_HardDisk, AccessMode_ReadWrite, FALSE /* fForceNewUuid */, pSourceDisk.asOutParam());
if (FAILED(rc)) throw rc;
Bstr uuidSource;
@@ -1620,43 +1627,43 @@ HRESULT Appliance::writeFSOVF(TaskOVF *pTask, AutoWriteLockBase& writeLock)
HRESULT rc = S_OK;
- PVDINTERFACEIO pSha1Callbacks = 0;
- PVDINTERFACEIO pFileCallbacks = 0;
+ PVDINTERFACEIO pShaIo = 0;
+ PVDINTERFACEIO pFileIo = 0;
do
{
- pSha1Callbacks = Sha1CreateInterface();
- if (!pSha1Callbacks)
+ pShaIo = ShaCreateInterface();
+ if (!pShaIo)
{
rc = E_OUTOFMEMORY;
break;
}
- pFileCallbacks = FileCreateInterface();
- if (!pFileCallbacks)
+ pFileIo = FileCreateInterface();
+ if (!pFileIo)
{
rc = E_OUTOFMEMORY;
break;
}
- SHA1STORAGE storage;
+ SHASTORAGE storage;
RT_ZERO(storage);
storage.fCreateDigest = m->fManifest;
- VDINTERFACE VDInterfaceIO;
- int vrc = VDInterfaceAdd(&VDInterfaceIO, "Appliance::IOFile",
- VDINTERFACETYPE_IO, pFileCallbacks,
- 0, &storage.pVDImageIfaces);
+ storage.fSha256 = m->fSha256;
+ int vrc = VDInterfaceAdd(&pFileIo->Core, "Appliance::IOFile",
+ VDINTERFACETYPE_IO, 0, sizeof(VDINTERFACEIO),
+ &storage.pVDImageIfaces);
if (RT_FAILURE(vrc))
{
rc = E_FAIL;
break;
}
- rc = writeFSImpl(pTask, writeLock, pSha1Callbacks, &storage);
+ rc = writeFSImpl(pTask, writeLock, pShaIo, &storage);
}while(0);
/* Cleanup */
- if (pSha1Callbacks)
- RTMemFree(pSha1Callbacks);
- if (pFileCallbacks)
- RTMemFree(pFileCallbacks);
+ if (pShaIo)
+ RTMemFree(pShaIo);
+ if (pFileIo)
+ RTMemFree(pFileIo);
LogFlowFuncLeave();
return rc;
@@ -1675,44 +1682,44 @@ HRESULT Appliance::writeFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock)
HRESULT rc = S_OK;
- PVDINTERFACEIO pSha1Callbacks = 0;
- PVDINTERFACEIO pTarCallbacks = 0;
+ PVDINTERFACEIO pShaIo = 0;
+ PVDINTERFACEIO pTarIo = 0;
do
{
- pSha1Callbacks = Sha1CreateInterface();
- if (!pSha1Callbacks)
+ pShaIo = ShaCreateInterface();
+ if (!pShaIo)
{
rc = E_OUTOFMEMORY;
break;
}
- pTarCallbacks = TarCreateInterface();
- if (!pTarCallbacks)
+ pTarIo = TarCreateInterface();
+ if (!pTarIo)
{
rc = E_OUTOFMEMORY;
break;
}
- VDINTERFACE VDInterfaceIO;
- SHA1STORAGE storage;
+ SHASTORAGE storage;
RT_ZERO(storage);
storage.fCreateDigest = m->fManifest;
- vrc = VDInterfaceAdd(&VDInterfaceIO, "Appliance::IOTar",
- VDINTERFACETYPE_IO, pTarCallbacks,
- tar, &storage.pVDImageIfaces);
+ storage.fSha256 = m->fSha256;
+ vrc = VDInterfaceAdd(&pTarIo->Core, "Appliance::IOTar",
+ VDINTERFACETYPE_IO, tar, sizeof(VDINTERFACEIO),
+ &storage.pVDImageIfaces);
if (RT_FAILURE(vrc))
{
rc = E_FAIL;
break;
}
- rc = writeFSImpl(pTask, writeLock, pSha1Callbacks, &storage);
+ rc = writeFSImpl(pTask, writeLock, pShaIo, &storage);
}while(0);
RTTarClose(tar);
/* Cleanup */
- if (pSha1Callbacks)
- RTMemFree(pSha1Callbacks);
- if (pTarCallbacks)
- RTMemFree(pTarCallbacks);
+ if (pShaIo)
+ RTMemFree(pShaIo);
+ if (pTarIo)
+ RTMemFree(pTarIo);
/* Delete ova file on error */
if(FAILED(rc))
@@ -1722,7 +1729,7 @@ HRESULT Appliance::writeFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock)
return rc;
}
-HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVDINTERFACEIO pCallbacks, PSHA1STORAGE pStorage)
+HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVDINTERFACEIO pIfIo, PSHASTORAGE pStorage)
{
LogFlowFuncEnter();
@@ -1754,7 +1761,7 @@ HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVD
tr("Could not create OVF file '%s'"),
strOvfFile.c_str());
/* Write the ovf file to disk. */
- vrc = Sha1WriteBuf(strOvfFile.c_str(), pvBuf, cbSize, pCallbacks, pStorage);
+ vrc = ShaWriteBuf(strOvfFile.c_str(), pvBuf, cbSize, pIfIo, pStorage);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR,
tr("Could not create OVF file '%s' (%Rrc)"),
@@ -1824,7 +1831,7 @@ HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVD
pDiskEntry->ulSizeMB); // operation's weight, as set up with the IProgress originally
// create a flat copy of the source disk image
- rc = pSourceDisk->exportFile(strTargetFilePath.c_str(), format, MediumVariant_VmdkStreamOptimized, pCallbacks, pStorage, pProgress2);
+ rc = pSourceDisk->exportFile(strTargetFilePath.c_str(), format, MediumVariant_VmdkStreamOptimized, pIfIo, pStorage, pProgress2);
if (FAILED(rc)) throw rc;
ComPtr<IProgress> pProgress3(pProgress2);
@@ -1862,7 +1869,8 @@ HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVD
}
void *pvBuf;
size_t cbSize;
- vrc = RTManifestWriteFilesBuf(&pvBuf, &cbSize, paManifestFiles, fileList.size());
+ vrc = RTManifestWriteFilesBuf(&pvBuf, &cbSize, m->fSha256 ? RTDIGESTTYPE_SHA256 : RTDIGESTTYPE_SHA1,
+ paManifestFiles, fileList.size());
RTMemFree(paManifestFiles);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR,
@@ -1871,7 +1879,7 @@ HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVD
/* Disable digest creation for the manifest file. */
pStorage->fCreateDigest = false;
/* Write the manifest file to disk. */
- vrc = Sha1WriteBuf(strMfFilePath.c_str(), pvBuf, cbSize, pCallbacks, pStorage);
+ vrc = ShaWriteBuf(strMfFilePath.c_str(), pvBuf, cbSize, pIfIo, pStorage);
RTMemFree(pvBuf);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR,
@@ -1896,7 +1904,7 @@ HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVD
for (it1 = fileList.begin();
it1 != fileList.end();
++it1)
- pCallbacks->pfnDelete(pStorage, (*it1).first.c_str());
+ pIfIo->pfnDelete(pStorage, (*it1).first.c_str());
}
LogFlowFunc(("rc=%Rhrc\n", rc));
@@ -1946,7 +1954,7 @@ HRESULT Appliance::writeS3(TaskOVF *pTask)
/* We need a temporary directory which we can put the OVF file & all
* disk images in */
- vrc = RTDirCreateTemp(pszTmpDir);
+ vrc = RTDirCreateTemp(pszTmpDir, 0700);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR,
tr("Cannot create temporary directory '%s' (%Rrc)"), pszTmpDir, vrc);
diff --git a/src/VBox/Main/src-server/ApplianceImplIO.cpp b/src/VBox/Main/src-server/ApplianceImplIO.cpp
index 992d6bd94..a31f93a80 100644
--- a/src/VBox/Main/src-server/ApplianceImplIO.cpp
+++ b/src/VBox/Main/src-server/ApplianceImplIO.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -52,7 +52,7 @@ typedef struct TARSTORAGEINTERNAL
PFNVDCOMPLETED pfnCompleted;
} TARSTORAGEINTERNAL, *PTARSTORAGEINTERNAL;
-typedef struct SHA1STORAGEINTERNAL
+typedef struct SHASTORAGEINTERNAL
{
/** Completion callback. */
PFNVDCOMPLETED pfnCompleted;
@@ -61,7 +61,7 @@ typedef struct SHA1STORAGEINTERNAL
/** Current file open mode. */
uint32_t fOpenMode;
/** Our own storage handle. */
- PSHA1STORAGE pSha1Storage;
+ PSHASTORAGE pShaStorage;
/** Circular buffer used for transferring data from/to the worker thread. */
PRTCIRCBUF pCircBuf;
/** Current absolute position (regardless of the real read/written data). */
@@ -76,8 +76,12 @@ typedef struct SHA1STORAGEINTERNAL
RTSEMEVENT newStatusEvent;
/** Event for signaling a finished task of the worker thread. */
RTSEMEVENT workFinishedEvent;
- /** SHA1 calculation context. */
- RTSHA1CONTEXT ctx;
+ /** SHA1/SHA256 calculation context. */
+ union
+ {
+ RTSHA1CONTEXT Sha1;
+ RTSHA256CONTEXT Sha256;
+ } ctx;
/** Write mode only: Memory buffer for writing zeros. */
void *pvZeroBuf;
/** Write mode only: Size of the zero memory buffer. */
@@ -86,7 +90,7 @@ typedef struct SHA1STORAGEINTERNAL
volatile bool fEOF;
// uint64_t calls;
// uint64_t waits;
-} SHA1STORAGEINTERNAL, *PSHA1STORAGEINTERNAL;
+} SHASTORAGEINTERNAL, *PSHASTORAGEINTERNAL;
/******************************************************************************
* Defined Constants And Macros *
@@ -293,7 +297,7 @@ static int tarOpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpen
*
*/
bool fFound = false;
- for(;;)
+ for (;;)
{
char *pszFilename = 0;
rc = RTTarCurrentFile(tar, &pszFilename);
@@ -309,7 +313,8 @@ static int tarOpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpen
if (RT_FAILURE(rc))
break;
}
- }else
+ }
+ else
break;
}
if (fFound)
@@ -457,20 +462,18 @@ static int tarFlushSyncCallback(void *pvUser, void *pvStorage)
}
/******************************************************************************
- * Internal: RTSha1 interface
+ * Internal: RTSha interface
******************************************************************************/
-DECLCALLBACK(int) sha1CalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
+DECLCALLBACK(int) shaCalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
- PSHA1STORAGEINTERNAL pInt = (PSHA1STORAGEINTERNAL)pvUser;
+ PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pInt->pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pInt->pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
int rc = VINF_SUCCESS;
bool fLoop = true;
@@ -497,7 +500,7 @@ DECLCALLBACK(int) sha1CalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
size_t cbMemAllRead = 0;
/* First loop over all the free memory in the circular
* memory buffer (could be turn around at the end). */
- for(;;)
+ for (;;)
{
if ( cbMemAllRead == cbAvail
|| fLoop == false)
@@ -511,13 +514,13 @@ DECLCALLBACK(int) sha1CalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
/* Second, write as long as used memory is there. The write
* method could also split the writes up into to smaller
* parts. */
- for(;;)
+ for (;;)
{
if (cbAllWritten == cbMemRead)
break;
size_t cbToWrite = cbMemRead - cbAllWritten;
size_t cbWritten = 0;
- rc = pCallbacks->pfnWriteSync(pIO->pvUser, pInt->pvStorage, pInt->cbCurFile, &pcBuf[cbAllWritten], cbToWrite, &cbWritten);
+ rc = vdIfIoFileWriteSync(pIfIo, pInt->pvStorage, pInt->cbCurFile, &pcBuf[cbAllWritten], cbToWrite, &cbWritten);
// RTPrintf ("%lu %lu %lu %Rrc\n", pInt->cbCurFile, cbToRead, cbRead, rc);
if (RT_FAILURE(rc))
{
@@ -527,10 +530,15 @@ DECLCALLBACK(int) sha1CalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
cbAllWritten += cbWritten;
pInt->cbCurFile += cbWritten;
}
- /* Update the SHA1 context with the next data block. */
+ /* Update the SHA1/SHA256 context with the next data block. */
if ( RT_SUCCESS(rc)
- && pInt->pSha1Storage->fCreateDigest)
- RTSha1Update(&pInt->ctx, pcBuf, cbAllWritten);
+ && pInt->pShaStorage->fCreateDigest)
+ {
+ if (pInt->pShaStorage->fSha256)
+ RTSha256Update(&pInt->ctx.Sha256, pcBuf, cbAllWritten);
+ else
+ RTSha1Update(&pInt->ctx.Sha1, pcBuf, cbAllWritten);
+ }
/* Mark the block as empty. */
RTCircBufReleaseReadBlock(pInt->pCircBuf, cbAllWritten);
cbMemAllRead += cbAllWritten;
@@ -549,7 +557,7 @@ DECLCALLBACK(int) sha1CalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
size_t cbMemAllWrite = 0;
/* First loop over all the available memory in the circular
* memory buffer (could be turn around at the end). */
- for(;;)
+ for (;;)
{
if ( cbMemAllWrite == cbAvail
|| fLoop == false)
@@ -563,13 +571,13 @@ DECLCALLBACK(int) sha1CalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
* read method could also split the reads up into to
* smaller parts. */
size_t cbAllRead = 0;
- for(;;)
+ for (;;)
{
if (cbAllRead == cbMemWrite)
break;
size_t cbToRead = cbMemWrite - cbAllRead;
size_t cbRead = 0;
- rc = pCallbacks->pfnReadSync(pIO->pvUser, pInt->pvStorage, pInt->cbCurFile, &pcBuf[cbAllRead], cbToRead, &cbRead);
+ rc = vdIfIoFileReadSync(pIfIo, pInt->pvStorage, pInt->cbCurFile, &pcBuf[cbAllRead], cbToRead, &cbRead);
// RTPrintf ("%lu %lu %lu %Rrc\n", pInt->cbCurFile, cbToRead, cbRead, rc);
if (RT_FAILURE(rc))
{
@@ -586,10 +594,15 @@ DECLCALLBACK(int) sha1CalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
cbAllRead += cbRead;
pInt->cbCurFile += cbRead;
}
- /* Update the SHA1 context with the next data block. */
+ /* Update the SHA1/SHA256 context with the next data block. */
if ( RT_SUCCESS(rc)
- && pInt->pSha1Storage->fCreateDigest)
- RTSha1Update(&pInt->ctx, pcBuf, cbAllRead);
+ && pInt->pShaStorage->fCreateDigest)
+ {
+ if (pInt->pShaStorage->fSha256)
+ RTSha256Update(&pInt->ctx.Sha256, pcBuf, cbAllRead);
+ else
+ RTSha1Update(&pInt->ctx.Sha1, pcBuf, cbAllRead);
+ }
/* Mark the block as full. */
RTCircBufReleaseWriteBlock(pInt->pCircBuf, cbAllRead);
cbMemAllWrite += cbAllRead;
@@ -615,17 +628,17 @@ DECLCALLBACK(int) sha1CalcWorkerThread(RTTHREAD /* aThread */, void *pvUser)
return rc;
}
-DECLINLINE(int) sha1SignalManifestThread(PSHA1STORAGEINTERNAL pInt, uint32_t uStatus)
+DECLINLINE(int) shaSignalManifestThread(PSHASTORAGEINTERNAL pInt, uint32_t uStatus)
{
ASMAtomicWriteU32(&pInt->u32Status, uStatus);
return RTSemEventSignal(pInt->newStatusEvent);
}
-DECLINLINE(int) sha1WaitForManifestThreadFinished(PSHA1STORAGEINTERNAL pInt)
+DECLINLINE(int) shaWaitForManifestThreadFinished(PSHASTORAGEINTERNAL pInt)
{
// RTPrintf("start\n");
int rc = VINF_SUCCESS;
- for(;;)
+ for (;;)
{
// RTPrintf(" wait\n");
uint32_t u32Status = ASMAtomicReadU32(&pInt->u32Status);
@@ -641,24 +654,24 @@ DECLINLINE(int) sha1WaitForManifestThreadFinished(PSHA1STORAGEINTERNAL pInt)
return rc;
}
-DECLINLINE(int) sha1FlushCurBuf(PSHA1STORAGEINTERNAL pInt)
+DECLINLINE(int) shaFlushCurBuf(PSHASTORAGEINTERNAL pInt)
{
int rc = VINF_SUCCESS;
if (pInt->fOpenMode & RTFILE_O_WRITE)
{
/* Let the write worker thread start immediately. */
- rc = sha1SignalManifestThread(pInt, STATUS_WRITE);
+ rc = shaSignalManifestThread(pInt, STATUS_WRITE);
if (RT_FAILURE(rc))
return rc;
/* Wait until the write worker thread has finished. */
- rc = sha1WaitForManifestThreadFinished(pInt);
+ rc = shaWaitForManifestThreadFinished(pInt);
}
return rc;
}
-static int sha1OpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpen,
+static int shaOpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpen,
PFNVDCOMPLETED pfnCompleted, void **ppInt)
{
/* Validate input. */
@@ -668,15 +681,13 @@ static int sha1OpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpe
AssertPtrReturn(ppInt, VERR_INVALID_POINTER);
AssertReturn((fOpen & RTFILE_O_READWRITE) != RTFILE_O_READWRITE, VERR_INVALID_PARAMETER); /* No read/write allowed */
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
DEBUG_PRINT_FLOW();
- PSHA1STORAGEINTERNAL pInt = (PSHA1STORAGEINTERNAL)RTMemAllocZ(sizeof(SHA1STORAGEINTERNAL));
+ PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)RTMemAllocZ(sizeof(SHASTORAGEINTERNAL));
if (!pInt)
return VERR_NO_MEMORY;
@@ -684,7 +695,7 @@ static int sha1OpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpe
do
{
pInt->pfnCompleted = pfnCompleted;
- pInt->pSha1Storage = pSha1Storage;
+ pInt->pShaStorage = pShaStorage;
pInt->fEOF = false;
pInt->fOpenMode = fOpen;
pInt->u32Status = STATUS_WAIT;
@@ -719,25 +730,29 @@ static int sha1OpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpe
if (RT_FAILURE(rc))
break;
/* Create the worker thread. */
- rc = RTThreadCreate(&pInt->pWorkerThread, sha1CalcWorkerThread, pInt, 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, RTTHREADFLAGS_WAITABLE, "SHA1-Worker");
+ rc = RTThreadCreate(&pInt->pWorkerThread, shaCalcWorkerThread, pInt, 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, RTTHREADFLAGS_WAITABLE, "SHA-Worker");
if (RT_FAILURE(rc))
break;
- if (pSha1Storage->fCreateDigest)
- /* Create a SHA1 context the worker thread will work with. */
- RTSha1Init(&pInt->ctx);
+ if (pShaStorage->fCreateDigest)
+ {
+ /* Create a SHA1/SHA256 context the worker thread will work with. */
+ if (pShaStorage->fSha256)
+ RTSha256Init(&pInt->ctx.Sha256);
+ else
+ RTSha1Init(&pInt->ctx.Sha1);
+ }
/* Open the file. */
- rc = pCallbacks->pfnOpen(pIO->pvUser, pszLocation,
- fOpen, pInt->pfnCompleted,
- &pInt->pvStorage);
+ rc = vdIfIoFileOpen(pIfIo, pszLocation, fOpen, pInt->pfnCompleted,
+ &pInt->pvStorage);
if (RT_FAILURE(rc))
break;
if (fOpen & RTFILE_O_READ)
{
/* Immediately let the worker thread start the reading. */
- rc = sha1SignalManifestThread(pInt, STATUS_READ);
+ rc = shaSignalManifestThread(pInt, STATUS_READ);
}
}
while(0);
@@ -746,7 +761,7 @@ static int sha1OpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpe
{
if (pInt->pWorkerThread)
{
- sha1SignalManifestThread(pInt, STATUS_END);
+ shaSignalManifestThread(pInt, STATUS_END);
RTThreadWait(pInt->pWorkerThread, RT_INDEFINITE_WAIT, 0);
}
if (pInt->workFinishedEvent)
@@ -765,54 +780,65 @@ static int sha1OpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpe
return rc;
}
-static int sha1CloseCallback(void *pvUser, void *pvStorage)
+static int shaCloseCallback(void *pvUser, void *pvStorage)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
AssertPtrReturn(pvStorage, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
- PSHA1STORAGEINTERNAL pInt = (PSHA1STORAGEINTERNAL)pvStorage;
+ PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvStorage;
DEBUG_PRINT_FLOW();
int rc = VINF_SUCCESS;
/* Make sure all pending writes are flushed */
- rc = sha1FlushCurBuf(pInt);
+ rc = shaFlushCurBuf(pInt);
if (pInt->pWorkerThread)
{
/* Signal the worker thread to end himself */
- rc = sha1SignalManifestThread(pInt, STATUS_END);
+ rc = shaSignalManifestThread(pInt, STATUS_END);
/* Worker thread stopped? */
rc = RTThreadWait(pInt->pWorkerThread, RT_INDEFINITE_WAIT, 0);
}
if ( RT_SUCCESS(rc)
- && pSha1Storage->fCreateDigest)
+ && pShaStorage->fCreateDigest)
{
- /* Finally calculate & format the SHA1 sum */
- unsigned char auchDig[RTSHA1_HASH_SIZE];
+ /* Finally calculate & format the SHA1/SHA256 sum */
+ unsigned char auchDig[RTSHA256_HASH_SIZE];
char *pszDigest;
- RTSha1Final(&pInt->ctx, auchDig);
- rc = RTStrAllocEx(&pszDigest, RTSHA1_DIGEST_LEN + 1);
+ size_t cbDigest;
+ if (pShaStorage->fSha256)
+ {
+ RTSha256Final(&pInt->ctx.Sha256, auchDig);
+ cbDigest = RTSHA256_DIGEST_LEN;
+ }
+ else
+ {
+ RTSha1Final(&pInt->ctx.Sha1, auchDig);
+ cbDigest = RTSHA1_DIGEST_LEN;
+ }
+ rc = RTStrAllocEx(&pszDigest, cbDigest + 1);
if (RT_SUCCESS(rc))
{
- rc = RTSha1ToString(auchDig, pszDigest, RTSHA1_DIGEST_LEN + 1);
+ if (pShaStorage->fSha256)
+ rc = RTSha256ToString(auchDig, pszDigest, cbDigest + 1);
+ else
+ rc = RTSha1ToString(auchDig, pszDigest, cbDigest + 1);
if (RT_SUCCESS(rc))
- pSha1Storage->strDigest = pszDigest;
+ pShaStorage->strDigest = pszDigest;
RTStrFree(pszDigest);
}
}
/* Close the file */
- rc = pCallbacks->pfnClose(pIO->pvUser, pInt->pvStorage);
+ rc = vdIfIoFileClose(pIfIo, pInt->pvStorage);
// RTPrintf("%lu %lu\n", pInt->calls, pInt->waits);
@@ -830,89 +856,80 @@ static int sha1CloseCallback(void *pvUser, void *pvStorage)
return rc;
}
-static int sha1DeleteCallback(void *pvUser, const char *pcszFilename)
+static int shaDeleteCallback(void *pvUser, const char *pcszFilename)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
DEBUG_PRINT_FLOW();
- return pCallbacks->pfnDelete(pIO->pvUser, pcszFilename);
+ return vdIfIoFileDelete(pIfIo, pcszFilename);
}
-static int sha1MoveCallback(void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove)
+static int shaMoveCallback(void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
+
DEBUG_PRINT_FLOW();
- return pCallbacks->pfnMove(pIO->pvUser, pcszSrc, pcszDst, fMove);
+ return vdIfIoFileMove(pIfIo, pcszSrc, pcszDst, fMove);
}
-static int sha1GetFreeSpaceCallback(void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace)
+static int shaGetFreeSpaceCallback(void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
DEBUG_PRINT_FLOW();
- return pCallbacks->pfnGetFreeSpace(pIO->pvUser, pcszFilename, pcbFreeSpace);
+ return vdIfIoFileGetFreeSpace(pIfIo, pcszFilename, pcbFreeSpace);
}
-static int sha1GetModificationTimeCallback(void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime)
+static int shaGetModificationTimeCallback(void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
DEBUG_PRINT_FLOW();
- return pCallbacks->pfnGetModificationTime(pIO->pvUser, pcszFilename, pModificationTime);
+ return vdIfIoFileGetModificationTime(pIfIo, pcszFilename, pModificationTime);
}
-static int sha1GetSizeCallback(void *pvUser, void *pvStorage, uint64_t *pcbSize)
+static int shaGetSizeCallback(void *pvUser, void *pvStorage, uint64_t *pcbSize)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
AssertPtrReturn(pvStorage, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
- PSHA1STORAGEINTERNAL pInt = (PSHA1STORAGEINTERNAL)pvStorage;
+ PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvStorage;
DEBUG_PRINT_FLOW();
uint64_t cbSize;
- int rc = pCallbacks->pfnGetSize(pIO->pvUser, pInt->pvStorage, &cbSize);
+ int rc = vdIfIoFileGetSize(pIfIo, pInt->pvStorage, &cbSize);
if (RT_FAILURE(rc))
return rc;
@@ -921,39 +938,35 @@ static int sha1GetSizeCallback(void *pvUser, void *pvStorage, uint64_t *pcbSize)
return VINF_SUCCESS;
}
-static int sha1SetSizeCallback(void *pvUser, void *pvStorage, uint64_t cbSize)
+static int shaSetSizeCallback(void *pvUser, void *pvStorage, uint64_t cbSize)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
AssertPtrReturn(pvStorage, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
- PSHA1STORAGEINTERNAL pInt = (PSHA1STORAGEINTERNAL)pvStorage;
+ PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvStorage;
DEBUG_PRINT_FLOW();
- return pCallbacks->pfnSetSize(pIO->pvUser, pInt->pvStorage, cbSize);
+ return vdIfIoFileSetSize(pIfIo, pInt->pvStorage, cbSize);
}
-static int sha1WriteSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset,
+static int shaWriteSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset,
const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
AssertPtrReturn(pvStorage, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
- PSHA1STORAGEINTERNAL pInt = (PSHA1STORAGEINTERNAL)pvStorage;
+ PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvStorage;
DEBUG_PRINT_FLOW();
@@ -968,15 +981,15 @@ static int sha1WriteSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset
{
size_t cbSize = (size_t)(uOffset - pInt->cbCurAll);
size_t cbAllWritten = 0;
- for(;;)
+ for (;;)
{
/* Finished? */
if (cbAllWritten == cbSize)
break;
size_t cbToWrite = RT_MIN(pInt->cbZeroBuf, cbSize - cbAllWritten);
size_t cbWritten = 0;
- rc = sha1WriteSyncCallback(pvUser, pvStorage, pInt->cbCurAll,
- pInt->pvZeroBuf, cbToWrite, &cbWritten);
+ rc = shaWriteSyncCallback(pvUser, pvStorage, pInt->cbCurAll,
+ pInt->pvZeroBuf, cbToWrite, &cbWritten);
if (RT_FAILURE(rc))
break;
cbAllWritten += cbWritten;
@@ -987,7 +1000,7 @@ static int sha1WriteSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset
// RTPrintf("Write uOffset: %7lu cbWrite: %7lu = %7lu\n", uOffset, cbWrite, uOffset + cbWrite);
size_t cbAllWritten = 0;
- for(;;)
+ for (;;)
{
/* Finished? */
if (cbAllWritten == cbWrite)
@@ -1000,13 +1013,13 @@ static int sha1WriteSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset
* writing some data. */
if ((cbWrite - cbAllWritten) > cbAvail)
{
- rc = sha1SignalManifestThread(pInt, STATUS_WRITE);
+ rc = shaSignalManifestThread(pInt, STATUS_WRITE);
if(RT_FAILURE(rc))
break;
/* If there is _no_ free space available, we have to wait until it is. */
if (cbAvail == 0)
{
- rc = sha1WaitForManifestThreadFinished(pInt);
+ rc = shaWaitForManifestThreadFinished(pInt);
if (RT_FAILURE(rc))
break;
cbAvail = RTCircBufFree(pInt->pCircBuf);
@@ -1032,27 +1045,25 @@ static int sha1WriteSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset
/* Signal the thread to write more data in the mean time. */
if ( RT_SUCCESS(rc)
&& RTCircBufUsed(pInt->pCircBuf) >= (RTCircBufSize(pInt->pCircBuf) / 2))
- rc = sha1SignalManifestThread(pInt, STATUS_WRITE);
+ rc = shaSignalManifestThread(pInt, STATUS_WRITE);
return rc;
}
-static int sha1ReadSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset,
- void *pvBuf, size_t cbRead, size_t *pcbRead)
+static int shaReadSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset,
+ void *pvBuf, size_t cbRead, size_t *pcbRead)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
AssertPtrReturn(pvStorage, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
// DEBUG_PRINT_FLOW();
- PSHA1STORAGEINTERNAL pInt = (PSHA1STORAGEINTERNAL)pvStorage;
+ PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvStorage;
int rc = VINF_SUCCESS;
@@ -1060,18 +1071,20 @@ static int sha1ReadSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset,
// RTPrintf("Read uOffset: %7lu cbRead: %7lu = %7lu\n", uOffset, cbRead, uOffset + cbRead);
/* Check if we jump forward in the file. If so we have to read the
- * remaining stuff in the gap anyway (SHA1; streaming). */
+ * remaining stuff in the gap anyway (SHA1/SHA256; streaming). */
if (pInt->cbCurAll < uOffset)
{
- rc = sha1ReadSyncCallback(pvUser, pvStorage, pInt->cbCurAll, 0,
- (size_t)(uOffset - pInt->cbCurAll), 0);
+ rc = shaReadSyncCallback(pvUser, pvStorage, pInt->cbCurAll, 0,
+ (size_t)(uOffset - pInt->cbCurAll), 0);
if (RT_FAILURE(rc))
return rc;
// RTPrintf("Gap Read uOffset: %7lu cbRead: %7lu = %7lu\n", uOffset, cbRead, uOffset + cbRead);
}
+ else if (uOffset < pInt->cbCurAll)
+ AssertMsgFailed(("Jumping backwards is not possible, sequential access is supported only\n"));
size_t cbAllRead = 0;
- for(;;)
+ for (;;)
{
/* Finished? */
if (cbAllRead == cbRead)
@@ -1087,13 +1100,13 @@ static int sha1ReadSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset,
* more. */
if ((cbRead - cbAllRead) > cbAvail)
{
- rc = sha1SignalManifestThread(pInt, STATUS_READ);
+ rc = shaSignalManifestThread(pInt, STATUS_READ);
if(RT_FAILURE(rc))
break;
/* If there is _no_ data available, we have to wait until it is. */
if (cbAvail == 0)
{
- rc = sha1WaitForManifestThreadFinished(pInt);
+ rc = shaWaitForManifestThreadFinished(pInt);
if (RT_FAILURE(rc))
break;
cbAvail = RTCircBufUsed(pInt->pCircBuf);
@@ -1124,58 +1137,54 @@ static int sha1ReadSyncCallback(void *pvUser, void *pvStorage, uint64_t uOffset,
/* Signal the thread to read more data in the mean time. */
if ( RT_SUCCESS(rc)
&& RTCircBufFree(pInt->pCircBuf) >= (RTCircBufSize(pInt->pCircBuf) / 2))
- rc = sha1SignalManifestThread(pInt, STATUS_READ);
+ rc = shaSignalManifestThread(pInt, STATUS_READ);
return rc;
}
-static int sha1FlushSyncCallback(void *pvUser, void *pvStorage)
+static int shaFlushSyncCallback(void *pvUser, void *pvStorage)
{
/* Validate input. */
AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
AssertPtrReturn(pvStorage, VERR_INVALID_POINTER);
- PSHA1STORAGE pSha1Storage = (PSHA1STORAGE)pvUser;
- PVDINTERFACE pIO = VDInterfaceGet(pSha1Storage->pVDImageIfaces, VDINTERFACETYPE_IO);
- AssertPtrReturn(pIO, VERR_INVALID_PARAMETER);
- PVDINTERFACEIO pCallbacks = VDGetInterfaceIO(pIO);
- AssertPtrReturn(pCallbacks, VERR_INVALID_PARAMETER);
+ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser;
+ PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces);
+ AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER);
DEBUG_PRINT_FLOW();
- PSHA1STORAGEINTERNAL pInt = (PSHA1STORAGEINTERNAL)pvStorage;
+ PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)pvStorage;
/* Check if there is still something in the buffer. If yes, flush it. */
- int rc = sha1FlushCurBuf(pInt);
+ int rc = shaFlushCurBuf(pInt);
if (RT_FAILURE(rc))
return rc;
- return pCallbacks->pfnFlushSync(pIO->pvUser, pInt->pvStorage);
+ return vdIfIoFileFlushSync(pIfIo, pInt->pvStorage);
}
/******************************************************************************
* Public Functions *
******************************************************************************/
-PVDINTERFACEIO Sha1CreateInterface()
+PVDINTERFACEIO ShaCreateInterface()
{
PVDINTERFACEIO pCallbacks = (PVDINTERFACEIO)RTMemAllocZ(sizeof(VDINTERFACEIO));
if (!pCallbacks)
return NULL;
- pCallbacks->cbSize = sizeof(VDINTERFACEIO);
- pCallbacks->enmInterface = VDINTERFACETYPE_IO;
- pCallbacks->pfnOpen = sha1OpenCallback;
- pCallbacks->pfnClose = sha1CloseCallback;
- pCallbacks->pfnDelete = sha1DeleteCallback;
- pCallbacks->pfnMove = sha1MoveCallback;
- pCallbacks->pfnGetFreeSpace = sha1GetFreeSpaceCallback;
- pCallbacks->pfnGetModificationTime = sha1GetModificationTimeCallback;
- pCallbacks->pfnGetSize = sha1GetSizeCallback;
- pCallbacks->pfnSetSize = sha1SetSizeCallback;
- pCallbacks->pfnReadSync = sha1ReadSyncCallback;
- pCallbacks->pfnWriteSync = sha1WriteSyncCallback;
- pCallbacks->pfnFlushSync = sha1FlushSyncCallback;
+ pCallbacks->pfnOpen = shaOpenCallback;
+ pCallbacks->pfnClose = shaCloseCallback;
+ pCallbacks->pfnDelete = shaDeleteCallback;
+ pCallbacks->pfnMove = shaMoveCallback;
+ pCallbacks->pfnGetFreeSpace = shaGetFreeSpaceCallback;
+ pCallbacks->pfnGetModificationTime = shaGetModificationTimeCallback;
+ pCallbacks->pfnGetSize = shaGetSizeCallback;
+ pCallbacks->pfnSetSize = shaSetSizeCallback;
+ pCallbacks->pfnReadSync = shaReadSyncCallback;
+ pCallbacks->pfnWriteSync = shaWriteSyncCallback;
+ pCallbacks->pfnFlushSync = shaFlushSyncCallback;
return pCallbacks;
}
@@ -1186,8 +1195,6 @@ PVDINTERFACEIO FileCreateInterface()
if (!pCallbacks)
return NULL;
- pCallbacks->cbSize = sizeof(VDINTERFACEIO);
- pCallbacks->enmInterface = VDINTERFACETYPE_IO;
pCallbacks->pfnOpen = fileOpenCallback;
pCallbacks->pfnClose = fileCloseCallback;
pCallbacks->pfnDelete = fileDeleteCallback;
@@ -1209,8 +1216,6 @@ PVDINTERFACEIO TarCreateInterface()
if (!pCallbacks)
return NULL;
- pCallbacks->cbSize = sizeof(VDINTERFACEIO);
- pCallbacks->enmInterface = VDINTERFACETYPE_IO;
pCallbacks->pfnOpen = tarOpenCallback;
pCallbacks->pfnClose = tarCloseCallback;
pCallbacks->pfnDelete = tarDeleteCallback;
@@ -1226,17 +1231,17 @@ PVDINTERFACEIO TarCreateInterface()
return pCallbacks;
}
-int Sha1ReadBuf(const char *pcszFilename, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, void *pvUser)
+int ShaReadBuf(const char *pcszFilename, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pIfIo, void *pvUser)
{
/* Validate input. */
AssertPtrReturn(ppvBuf, VERR_INVALID_POINTER);
AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
- AssertPtrReturn(pCallbacks, VERR_INVALID_POINTER);
+ AssertPtrReturn(pIfIo, VERR_INVALID_POINTER);
void *pvStorage;
- int rc = pCallbacks->pfnOpen(pvUser, pcszFilename,
- RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, 0,
- &pvStorage);
+ int rc = pIfIo->pfnOpen(pvUser, pcszFilename,
+ RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE, 0,
+ &pvStorage);
if (RT_FAILURE(rc))
return rc;
@@ -1253,10 +1258,10 @@ int Sha1ReadBuf(const char *pcszFilename, void **ppvBuf, size_t *pcbSize, PVDINT
break;
}
- for(;;)
+ for (;;)
{
size_t cbRead = 0;
- rc = pCallbacks->pfnReadSync(pvUser, pvStorage, cbAllRead, pvTmpBuf, cbTmpSize, &cbRead);
+ rc = pIfIo->pfnReadSync(pvUser, pvStorage, cbAllRead, pvTmpBuf, cbTmpSize, &cbRead);
if ( RT_FAILURE(rc)
|| cbRead == 0)
break;
@@ -1271,7 +1276,7 @@ int Sha1ReadBuf(const char *pcszFilename, void **ppvBuf, size_t *pcbSize, PVDINT
}
}while(0);
- pCallbacks->pfnClose(pvUser, pvStorage);
+ pIfIo->pfnClose(pvUser, pvStorage);
if (rc == VERR_EOF)
rc = VINF_SUCCESS;
@@ -1283,7 +1288,8 @@ int Sha1ReadBuf(const char *pcszFilename, void **ppvBuf, size_t *pcbSize, PVDINT
{
*ppvBuf = pvBuf;
*pcbSize = cbAllRead;
- }else
+ }
+ else
{
if (pvBuf)
RTMemFree(pvBuf);
@@ -1292,34 +1298,34 @@ int Sha1ReadBuf(const char *pcszFilename, void **ppvBuf, size_t *pcbSize, PVDINT
return rc;
}
-int Sha1WriteBuf(const char *pcszFilename, void *pvBuf, size_t cbSize, PVDINTERFACEIO pCallbacks, void *pvUser)
+int ShaWriteBuf(const char *pcszFilename, void *pvBuf, size_t cbSize, PVDINTERFACEIO pIfIo, void *pvUser)
{
/* Validate input. */
AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
AssertReturn(cbSize, VERR_INVALID_PARAMETER);
- AssertPtrReturn(pCallbacks, VERR_INVALID_POINTER);
+ AssertPtrReturn(pIfIo, VERR_INVALID_POINTER);
void *pvStorage;
- int rc = pCallbacks->pfnOpen(pvUser, pcszFilename,
- RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_ALL, 0,
- &pvStorage);
+ int rc = pIfIo->pfnOpen(pvUser, pcszFilename,
+ RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_ALL, 0,
+ &pvStorage);
if (RT_FAILURE(rc))
return rc;
size_t cbAllWritten = 0;
- for(;;)
+ for (;;)
{
if (cbAllWritten >= cbSize)
break;
size_t cbToWrite = cbSize - cbAllWritten;
size_t cbWritten = 0;
- rc = pCallbacks->pfnWriteSync(pvUser, pvStorage, cbAllWritten, &((char*)pvBuf)[cbAllWritten], cbToWrite, &cbWritten);
+ rc = pIfIo->pfnWriteSync(pvUser, pvStorage, cbAllWritten, &((char*)pvBuf)[cbAllWritten], cbToWrite, &cbWritten);
if (RT_FAILURE(rc))
break;
cbAllWritten += cbWritten;
}
- pCallbacks->pfnClose(pvUser, pvStorage);
+ pIfIo->pfnClose(pvUser, pvStorage);
return rc;
}
diff --git a/src/VBox/Main/src-server/ApplianceImplImport.cpp b/src/VBox/Main/src-server/ApplianceImplImport.cpp
index f02253b45..447d717fc 100644
--- a/src/VBox/Main/src-server/ApplianceImplImport.cpp
+++ b/src/VBox/Main/src-server/ApplianceImplImport.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2008-2011 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -191,7 +191,7 @@ STDMETHODIMP Appliance::Interpret()
nameVBox = pNewDesc->m->pConfig->machineUserData.strName;
else
nameVBox = vsysThis.strName;
- /* If the there isn't any name specified create a default one out
+ /* If there isn't any name specified create a default one out
* of the OS type */
if (nameVBox.isEmpty())
nameVBox = strOsTypeVBox;
@@ -204,7 +204,9 @@ STDMETHODIMP Appliance::Interpret()
/* Based on the VM name, create a target machine path. */
Bstr bstrMachineFilename;
rc = mVirtualBox->ComposeMachineFilename(Bstr(nameVBox).raw(),
- NULL,
+ NULL /* aGroup */,
+ NULL /* aCreateFlags */,
+ NULL /* aBaseFolder */,
bstrMachineFilename.asOutParam());
if (FAILED(rc)) throw rc;
/* Determine the machine folder from that */
@@ -352,16 +354,18 @@ STDMETHODIMP Appliance::Interpret()
/* If there is a <vbox:Machine>, we always prefer the setting from there. */
if (vsysThis.pelmVboxMachine)
{
+ uint32_t maxNetworkAdapters = Global::getMaxNetworkAdapters(pNewDesc->m->pConfig->hardwareMachine.chipsetType);
+
const settings::NetworkAdaptersList &llNetworkAdapters = pNewDesc->m->pConfig->hardwareMachine.llNetworkAdapters;
/* Check for the constrains */
- if (llNetworkAdapters.size() > SchemaDefs::NetworkAdapterCount)
+ if (llNetworkAdapters.size() > maxNetworkAdapters)
addWarning(tr("The virtual system \"%s\" claims support for %zu network adapters, but VirtualBox has support for max %u network adapter only."),
- vsysThis.strName.c_str(), llNetworkAdapters.size(), SchemaDefs::NetworkAdapterCount);
+ vsysThis.strName.c_str(), llNetworkAdapters.size(), maxNetworkAdapters);
/* Iterate through all network adapters. */
settings::NetworkAdaptersList::const_iterator it1;
size_t a = 0;
for (it1 = llNetworkAdapters.begin();
- it1 != llNetworkAdapters.end() && a < SchemaDefs::NetworkAdapterCount;
+ it1 != llNetworkAdapters.end() && a < maxNetworkAdapters;
++it1, ++a)
{
if (it1->fEnabled)
@@ -379,10 +383,12 @@ STDMETHODIMP Appliance::Interpret()
/* else we use the ovf configuration. */
else if (size_t cEthernetAdapters = vsysThis.llEthernetAdapters.size() > 0)
{
+ uint32_t maxNetworkAdapters = Global::getMaxNetworkAdapters(ChipsetType_PIIX3);
+
/* Check for the constrains */
- if (cEthernetAdapters > SchemaDefs::NetworkAdapterCount)
+ if (cEthernetAdapters > maxNetworkAdapters)
addWarning(tr("The virtual system \"%s\" claims support for %zu network adapters, but VirtualBox has support for max %u network adapter only."),
- vsysThis.strName.c_str(), cEthernetAdapters, SchemaDefs::NetworkAdapterCount);
+ vsysThis.strName.c_str(), cEthernetAdapters, maxNetworkAdapters);
/* Get the default network adapter type for the selected guest OS */
NetworkAdapterType_T defaultAdapterVBox = NetworkAdapterType_Am79C970A;
@@ -390,11 +396,11 @@ STDMETHODIMP Appliance::Interpret()
if (FAILED(rc)) throw rc;
ovf::EthernetAdaptersList::const_iterator itEA;
- /* Iterate through all abstract networks. We support 8 network
- * adapters at the maximum, so the first 8 will be added only. */
+ /* Iterate through all abstract networks. Ignore network cards
+ * which exceed the limit of VirtualBox. */
size_t a = 0;
for (itEA = vsysThis.llEthernetAdapters.begin();
- itEA != vsysThis.llEthernetAdapters.end() && a < SchemaDefs::NetworkAdapterCount;
+ itEA != vsysThis.llEthernetAdapters.end() && a < maxNetworkAdapters;
++itEA, ++a)
{
const ovf::EthernetAdapter &ea = *itEA; // logical network to connect to
@@ -813,42 +819,41 @@ HRESULT Appliance::readFSOVF(TaskOVF *pTask)
HRESULT rc = S_OK;
- PVDINTERFACEIO pSha1Callbacks = 0;
- PVDINTERFACEIO pFileCallbacks = 0;
+ PVDINTERFACEIO pShaIo = 0;
+ PVDINTERFACEIO pFileIo = 0;
do
{
- pSha1Callbacks = Sha1CreateInterface();
- if (!pSha1Callbacks)
+ pShaIo = ShaCreateInterface();
+ if (!pShaIo)
{
rc = E_OUTOFMEMORY;
break;
}
- pFileCallbacks = FileCreateInterface();
- if (!pFileCallbacks)
+ pFileIo = FileCreateInterface();
+ if (!pFileIo)
{
rc = E_OUTOFMEMORY;
break;
}
- VDINTERFACE VDInterfaceIO;
- SHA1STORAGE storage;
+ SHASTORAGE storage;
RT_ZERO(storage);
- int vrc = VDInterfaceAdd(&VDInterfaceIO, "Appliance::IOFile",
- VDINTERFACETYPE_IO, pFileCallbacks,
- 0, &storage.pVDImageIfaces);
+ int vrc = VDInterfaceAdd(&pFileIo->Core, "Appliance::IOFile",
+ VDINTERFACETYPE_IO, 0, sizeof(VDINTERFACEIO),
+ &storage.pVDImageIfaces);
if (RT_FAILURE(vrc))
{
- rc = E_FAIL;
+ rc = setError(VBOX_E_IPRT_ERROR, "Creation of the VD interface failed (%Rrc)", vrc);
break;
}
- rc = readFSImpl(pTask, pTask->locInfo.strPath, pSha1Callbacks, &storage);
+ rc = readFSImpl(pTask, pTask->locInfo.strPath, pShaIo, &storage);
}while(0);
/* Cleanup */
- if (pSha1Callbacks)
- RTMemFree(pSha1Callbacks);
- if (pFileCallbacks)
- RTMemFree(pFileCallbacks);
+ if (pShaIo)
+ RTMemFree(pShaIo);
+ if (pFileIo)
+ RTMemFree(pFileIo);
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
@@ -869,8 +874,8 @@ HRESULT Appliance::readFSOVA(TaskOVF *pTask)
HRESULT rc = S_OK;
- PVDINTERFACEIO pSha1Callbacks = 0;
- PVDINTERFACEIO pTarCallbacks = 0;
+ PVDINTERFACEIO pShaIo = 0;
+ PVDINTERFACEIO pTarIo = 0;
char *pszFilename = 0;
do
{
@@ -880,30 +885,29 @@ HRESULT Appliance::readFSOVA(TaskOVF *pTask)
rc = VBOX_E_FILE_ERROR;
break;
}
- pSha1Callbacks = Sha1CreateInterface();
- if (!pSha1Callbacks)
+ pShaIo = ShaCreateInterface();
+ if (!pShaIo)
{
rc = E_OUTOFMEMORY;
break;
}
- pTarCallbacks = TarCreateInterface();
- if (!pTarCallbacks)
+ pTarIo = TarCreateInterface();
+ if (!pTarIo)
{
rc = E_OUTOFMEMORY;
break;
}
- VDINTERFACE VDInterfaceIO;
- SHA1STORAGE storage;
+ SHASTORAGE storage;
RT_ZERO(storage);
- vrc = VDInterfaceAdd(&VDInterfaceIO, "Appliance::IOTar",
- VDINTERFACETYPE_IO, pTarCallbacks,
- tar, &storage.pVDImageIfaces);
+ vrc = VDInterfaceAdd(&pTarIo->Core, "Appliance::IOTar",
+ VDINTERFACETYPE_IO, tar, sizeof(VDINTERFACEIO),
+ &storage.pVDImageIfaces);
if (RT_FAILURE(vrc))
{
- rc = E_FAIL;
+ rc = setError(VBOX_E_IPRT_ERROR, "Creation of the VD interface failed (%Rrc)", vrc);
break;
}
- rc = readFSImpl(pTask, pszFilename, pSha1Callbacks, &storage);
+ rc = readFSImpl(pTask, pszFilename, pShaIo, &storage);
}while(0);
RTTarClose(tar);
@@ -911,10 +915,10 @@ HRESULT Appliance::readFSOVA(TaskOVF *pTask)
/* Cleanup */
if (pszFilename)
RTMemFree(pszFilename);
- if (pSha1Callbacks)
- RTMemFree(pSha1Callbacks);
- if (pTarCallbacks)
- RTMemFree(pTarCallbacks);
+ if (pShaIo)
+ RTMemFree(pShaIo);
+ if (pTarIo)
+ RTMemFree(pTarIo);
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
@@ -922,7 +926,7 @@ HRESULT Appliance::readFSOVA(TaskOVF *pTask)
return rc;
}
-HRESULT Appliance::readFSImpl(TaskOVF *pTask, const RTCString &strFilename, PVDINTERFACEIO pCallbacks, PSHA1STORAGE pStorage)
+HRESULT Appliance::readFSImpl(TaskOVF *pTask, const RTCString &strFilename, PVDINTERFACEIO pIfIo, PSHASTORAGE pStorage)
{
LogFlowFuncEnter();
@@ -935,14 +939,14 @@ HRESULT Appliance::readFSImpl(TaskOVF *pTask, const RTCString &strFilename, PVDI
{
/* Read the OVF into a memory buffer */
size_t cbSize = 0;
- int vrc = Sha1ReadBuf(strFilename.c_str(), &pvTmpBuf, &cbSize, pCallbacks, pStorage);
+ int vrc = ShaReadBuf(strFilename.c_str(), &pvTmpBuf, &cbSize, pIfIo, pStorage);
if ( RT_FAILURE(vrc)
|| !pvTmpBuf)
throw setError(VBOX_E_FILE_ERROR,
tr("Could not read OVF file '%s' (%Rrc)"),
RTPathFilename(strFilename.c_str()), vrc);
- /* Copy the SHA1 sum of the OVF file for later validation */
- m->strOVFSHA1Digest = pStorage->strDigest;
+ /* Copy the SHA1/SHA256 sum of the OVF file for later validation */
+ m->strOVFSHADigest = pStorage->strDigest;
/* Read & parse the XML structure of the OVF file */
m->pReader = new ovf::OVFReader(pvTmpBuf, cbSize, pTask->locInfo.strPath);
}
@@ -1004,7 +1008,7 @@ HRESULT Appliance::readS3(TaskOVF *pTask)
/* We need a temporary directory which we can put the OVF file & all
* disk images in */
- vrc = RTDirCreateTemp(pszTmpDir);
+ vrc = RTDirCreateTemp(pszTmpDir, 0700);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR,
tr("Cannot create temporary directory '%s'"), pszTmpDir);
@@ -1230,48 +1234,51 @@ HRESULT Appliance::importFSOVF(TaskOVF *pTask, AutoWriteLockBase& writeLock)
HRESULT rc = S_OK;
- PVDINTERFACEIO pSha1Callbacks = 0;
- PVDINTERFACEIO pFileCallbacks = 0;
- void *pvMfBuf = 0;
+ PVDINTERFACEIO pShaIo = NULL;
+ PVDINTERFACEIO pFileIo = NULL;
+ void *pvMfBuf = NULL;
writeLock.release();
try
{
/* Create the necessary file access interfaces. */
- pSha1Callbacks = Sha1CreateInterface();
- if (!pSha1Callbacks)
- throw E_OUTOFMEMORY;
- pFileCallbacks = FileCreateInterface();
- if (!pFileCallbacks)
- throw E_OUTOFMEMORY;
-
- VDINTERFACE VDInterfaceIO;
- SHA1STORAGE storage;
- RT_ZERO(storage);
- storage.fCreateDigest = true;
- int vrc = VDInterfaceAdd(&VDInterfaceIO, "Appliance::IOFile",
- VDINTERFACETYPE_IO, pFileCallbacks,
- 0, &storage.pVDImageIfaces);
- if (RT_FAILURE(vrc))
- throw E_FAIL;
+ pFileIo = FileCreateInterface();
+ if (!pFileIo)
+ throw setError(E_OUTOFMEMORY);
- size_t cbMfSize = 0;
Utf8Str strMfFile = Utf8Str(pTask->locInfo.strPath).stripExt().append(".mf");
/* Create the import stack for the rollback on errors. */
ImportStack stack(pTask->locInfo, m->pReader->m_mapDisks, pTask->pProgress);
- /* Do we need the digest information? */
- storage.fCreateDigest = RTFileExists(strMfFile.c_str());
- /* Now import the appliance. */
- importMachines(stack, pSha1Callbacks, &storage);
- /* Read & verify the manifest file, if there is one. */
- if (storage.fCreateDigest)
+
+ if (RTFileExists(strMfFile.c_str()))
{
+ SHASTORAGE storage;
+ RT_ZERO(storage);
+
+ pShaIo = ShaCreateInterface();
+ if (!pShaIo)
+ throw setError(E_OUTOFMEMORY);
+
+ storage.fCreateDigest = true;
+ int vrc = VDInterfaceAdd(&pFileIo->Core, "Appliance::IOFile",
+ VDINTERFACETYPE_IO, 0, sizeof(VDINTERFACEIO),
+ &storage.pVDImageIfaces);
+ if (RT_FAILURE(vrc))
+ throw setError(VBOX_E_IPRT_ERROR, "Creation of the VD interface failed (%Rrc)", vrc);
+
+ size_t cbMfSize = 0;
+ storage.fCreateDigest = true;
+ /* Now import the appliance. */
+ importMachines(stack, pShaIo, &storage);
+ /* Read & verify the manifest file. */
/* Add the ovf file to the digest list. */
- stack.llSrcDisksDigest.push_front(STRPAIR(pTask->locInfo.strPath, m->strOVFSHA1Digest));
- rc = readManifestFile(strMfFile, &pvMfBuf, &cbMfSize, pSha1Callbacks, &storage);
+ stack.llSrcDisksDigest.push_front(STRPAIR(pTask->locInfo.strPath, m->strOVFSHADigest));
+ rc = readManifestFile(strMfFile, &pvMfBuf, &cbMfSize, pShaIo, &storage);
if (FAILED(rc)) throw rc;
rc = verifyManifestFile(strMfFile, stack, pvMfBuf, cbMfSize);
if (FAILED(rc)) throw rc;
}
+ else
+ importMachines(stack, pFileIo, NULL);
}
catch (HRESULT rc2)
{
@@ -1282,10 +1289,10 @@ HRESULT Appliance::importFSOVF(TaskOVF *pTask, AutoWriteLockBase& writeLock)
/* Cleanup */
if (pvMfBuf)
RTMemFree(pvMfBuf);
- if (pSha1Callbacks)
- RTMemFree(pSha1Callbacks);
- if (pFileCallbacks)
- RTMemFree(pFileCallbacks);
+ if (pShaIo)
+ RTMemFree(pShaIo);
+ if (pFileIo)
+ RTMemFree(pFileIo);
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
@@ -1306,46 +1313,45 @@ HRESULT Appliance::importFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock)
HRESULT rc = S_OK;
- PVDINTERFACEIO pSha1Callbacks = 0;
- PVDINTERFACEIO pTarCallbacks = 0;
+ PVDINTERFACEIO pShaIo = 0;
+ PVDINTERFACEIO pTarIo = 0;
char *pszFilename = 0;
void *pvMfBuf = 0;
writeLock.release();
try
{
/* Create the necessary file access interfaces. */
- pSha1Callbacks = Sha1CreateInterface();
- if (!pSha1Callbacks)
- throw E_OUTOFMEMORY;
- pTarCallbacks = TarCreateInterface();
- if (!pTarCallbacks)
- throw E_OUTOFMEMORY;
-
- VDINTERFACE VDInterfaceIO;
- SHA1STORAGE storage;
+ pShaIo = ShaCreateInterface();
+ if (!pShaIo)
+ throw setError(E_OUTOFMEMORY);
+ pTarIo = TarCreateInterface();
+ if (!pTarIo)
+ throw setError(E_OUTOFMEMORY);
+
+ SHASTORAGE storage;
RT_ZERO(storage);
- vrc = VDInterfaceAdd(&VDInterfaceIO, "Appliance::IOTar",
- VDINTERFACETYPE_IO, pTarCallbacks,
- tar, &storage.pVDImageIfaces);
+ vrc = VDInterfaceAdd(&pTarIo->Core, "Appliance::IOTar",
+ VDINTERFACETYPE_IO, tar, sizeof(VDINTERFACEIO),
+ &storage.pVDImageIfaces);
if (RT_FAILURE(vrc))
- throw setError(E_FAIL,
- tr("Internal error (%Rrc)"), vrc);
+ throw setError(VBOX_E_IPRT_ERROR,
+ tr("Creation of the VD interface failed (%Rrc)"), vrc);
/* Read the file name of the first file (need to be the ovf file). This
* is how all internal files are named. */
vrc = RTTarCurrentFile(tar, &pszFilename);
if (RT_FAILURE(vrc))
- throw setError(E_FAIL,
- tr("Internal error (%Rrc)"), vrc);
+ throw setError(VBOX_E_IPRT_ERROR,
+ tr("Getting the current file within the archive failed (%Rrc)"), vrc);
/* Skip the OVF file, cause this was read in IAppliance::Read already. */
vrc = RTTarSeekNextFile(tar);
if ( RT_FAILURE(vrc)
&& vrc != VERR_TAR_END_OF_FILE)
- throw setError(E_FAIL,
- tr("Internal error (%Rrc)"), vrc);
+ throw setError(VBOX_E_IPRT_ERROR,
+ tr("Seeking within the archive failed (%Rrc)"), vrc);
- PVDINTERFACEIO pCallbacks = pSha1Callbacks;
- PSHA1STORAGE pStorage = &storage;
+ PVDINTERFACEIO pCallbacks = pShaIo;
+ PSHASTORAGE pStorage = &storage;
/* We always need to create the digest, cause we didn't know if there
* is a manifest file in the stream. */
@@ -1381,7 +1387,7 @@ HRESULT Appliance::importFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock)
if (pvMfBuf)
{
/* Add the ovf file to the digest list. */
- stack.llSrcDisksDigest.push_front(STRPAIR(Utf8Str(pszFilename).stripExt().append(".ovf"), m->strOVFSHA1Digest));
+ stack.llSrcDisksDigest.push_front(STRPAIR(Utf8Str(pszFilename).stripExt().append(".ovf"), m->strOVFSHADigest));
rc = verifyManifestFile(strMfFile, stack, pvMfBuf, cbMfSize);
if (FAILED(rc)) throw rc;
}
@@ -1399,10 +1405,10 @@ HRESULT Appliance::importFSOVA(TaskOVF *pTask, AutoWriteLockBase& writeLock)
RTMemFree(pszFilename);
if (pvMfBuf)
RTMemFree(pvMfBuf);
- if (pSha1Callbacks)
- RTMemFree(pSha1Callbacks);
- if (pTarCallbacks)
- RTMemFree(pTarCallbacks);
+ if (pShaIo)
+ RTMemFree(pShaIo);
+ if (pTarIo)
+ RTMemFree(pTarIo);
LogFlowFunc(("rc=%Rhrc\n", rc));
LogFlowFuncLeave();
@@ -1446,7 +1452,7 @@ HRESULT Appliance::importS3(TaskOVF *pTask)
/* We need a temporary directory which we can put the all disk images
* in */
- vrc = RTDirCreateTemp(pszTmpDir);
+ vrc = RTDirCreateTemp(pszTmpDir, 0700);
if (RT_FAILURE(vrc))
throw setError(VBOX_E_FILE_ERROR,
tr("Cannot create temporary directory '%s' (%Rrc)"), pszTmpDir, vrc);
@@ -1603,13 +1609,13 @@ HRESULT Appliance::importS3(TaskOVF *pTask)
}
#endif /* VBOX_WITH_S3 */
-HRESULT Appliance::readManifestFile(const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHA1STORAGE pStorage)
+HRESULT Appliance::readManifestFile(const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHASTORAGE pStorage)
{
HRESULT rc = S_OK;
bool fOldDigest = pStorage->fCreateDigest;
pStorage->fCreateDigest = false; /* No digest for the manifest file */
- int vrc = Sha1ReadBuf(strFile.c_str(), ppvBuf, pcbSize, pCallbacks, pStorage);
+ int vrc = ShaReadBuf(strFile.c_str(), ppvBuf, pcbSize, pCallbacks, pStorage);
if ( RT_FAILURE(vrc)
&& vrc != VERR_FILE_NOT_FOUND)
rc = setError(VBOX_E_FILE_ERROR,
@@ -1620,7 +1626,7 @@ HRESULT Appliance::readManifestFile(const Utf8Str &strFile, void **ppvBuf, size_
return rc;
}
-HRESULT Appliance::readTarManifestFile(RTTAR tar, const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHA1STORAGE pStorage)
+HRESULT Appliance::readTarManifestFile(RTTAR tar, const Utf8Str &strFile, void **ppvBuf, size_t *pcbSize, PVDINTERFACEIO pCallbacks, PSHASTORAGE pStorage)
{
HRESULT rc = S_OK;
@@ -1633,7 +1639,7 @@ HRESULT Appliance::readTarManifestFile(RTTAR tar, const Utf8Str &strFile, void *
RTStrFree(pszCurFile);
}
else if (vrc != VERR_TAR_END_OF_FILE)
- rc = E_FAIL;
+ rc = setError(VBOX_E_IPRT_ERROR, "Seeking within the archive failed (%Rrc)", vrc);
return rc;
}
@@ -1794,7 +1800,7 @@ void Appliance::importOneDiskImage(const ovf::DiskImage &di,
ComObjPtr<Medium> &pTargetHD,
ImportStack &stack,
PVDINTERFACEIO pCallbacks,
- PSHA1STORAGE pStorage)
+ PSHASTORAGE pStorage)
{
ComObjPtr<Progress> pProgress;
pProgress.createObject();
@@ -1846,8 +1852,7 @@ void Appliance::importOneDiskImage(const ovf::DiskImage &di,
rc = pTargetHD->init(mVirtualBox,
strTrgFormat,
strTargetPath,
- Guid::Empty, // media registry: none yet
- NULL /* llRegistriesThatNeedSaving */);
+ Guid::Empty /* media registry: none yet */);
if (FAILED(rc)) throw rc;
/* Now create an empty hard disk. */
@@ -1912,7 +1917,7 @@ void Appliance::importOneDiskImage(const ovf::DiskImage &di,
/* Add the newly create disk path + a corresponding digest the our list for
* later manifest verification. */
- stack.llSrcDisksDigest.push_back(STRPAIR(strSrcFilePath, pStorage->strDigest));
+ stack.llSrcDisksDigest.push_back(STRPAIR(strSrcFilePath, pStorage ? pStorage->strDigest : ""));
}
/**
@@ -1933,7 +1938,7 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
ComPtr<IMachine> &pNewMachine,
ImportStack &stack,
PVDINTERFACEIO pCallbacks,
- PSHA1STORAGE pStorage)
+ PSHASTORAGE pStorage)
{
HRESULT rc;
@@ -1944,11 +1949,12 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
if (FAILED(rc)) throw rc;
/* Create the machine */
+ SafeArray<BSTR> groups; /* no groups */
rc = mVirtualBox->CreateMachine(NULL, /* machine name: use default */
Bstr(stack.strNameVBox).raw(),
+ ComSafeArrayAsInParam(groups),
Bstr(stack.strOsTypeVBox).raw(),
- NULL, /* uuid */
- FALSE, /* fForceOverwrite */
+ NULL, /* aCreateFlags */
pNewMachine.asOutParam());
if (FAILED(rc)) throw rc;
@@ -2029,6 +2035,8 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
#endif /* VBOX_WITH_USB */
/* Change the network adapters */
+ uint32_t maxNetworkAdapters = Global::getMaxNetworkAdapters(ChipsetType_PIIX3);
+
std::list<VirtualSystemDescriptionEntry*> vsdeNW = vsdescThis->findByType(VirtualSystemDescriptionType_NetworkAdapter);
if (vsdeNW.size() == 0)
{
@@ -2039,10 +2047,10 @@ void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
rc = nwVBox->COMSETTER(Enabled)(false);
if (FAILED(rc)) throw rc;
}
- else if (vsdeNW.size() > SchemaDefs::NetworkAdapterCount)
+ else if (vsdeNW.size() > maxNetworkAdapters)
throw setError(VBOX_E_FILE_ERROR,
tr("Too many network adapters: OVF requests %d network adapters, but VirtualBox only supports %d"),
- vsdeNW.size(), SchemaDefs::NetworkAdapterCount);
+ vsdeNW.size(), maxNetworkAdapters);
else
{
list<VirtualSystemDescriptionEntry*>::const_iterator nwIt;
@@ -2499,7 +2507,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
ComPtr<IMachine> &pReturnNewMachine,
ImportStack &stack,
PVDINTERFACEIO pCallbacks,
- PSHA1STORAGE pStorage)
+ PSHASTORAGE pStorage)
{
Assert(vsdescThis->m->pConfig);
@@ -2811,7 +2819,7 @@ void Appliance::importVBoxMachine(ComObjPtr<VirtualSystemDescription> &vsdescThi
void Appliance::importMachines(ImportStack &stack,
PVDINTERFACEIO pCallbacks,
- PSHA1STORAGE pStorage)
+ PSHASTORAGE pStorage)
{
HRESULT rc = S_OK;
@@ -2858,7 +2866,9 @@ void Appliance::importMachines(ImportStack &stack,
// put the disk images in the same directory
Bstr bstrMachineFilename;
rc = mVirtualBox->ComposeMachineFilename(Bstr(stack.strNameVBox).raw(),
- NULL,
+ NULL /* aGroup */,
+ NULL /* aCreateFlags */,
+ NULL /* aBaseFolder */,
bstrMachineFilename.asOutParam());
if (FAILED(rc)) throw rc;
// and determine the machine folder from that
diff --git a/src/VBox/Main/src-server/BandwidthControlImpl.cpp b/src/VBox/Main/src-server/BandwidthControlImpl.cpp
index 927a8007a..70e2d2431 100644
--- a/src/VBox/Main/src-server/BandwidthControlImpl.cpp
+++ b/src/VBox/Main/src-server/BandwidthControlImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2009 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -409,8 +409,12 @@ HRESULT BandwidthControl::getBandwidthGroupByName(const Utf8Str &aName,
return VBOX_E_OBJECT_NOT_FOUND;
}
-STDMETHODIMP BandwidthControl::CreateBandwidthGroup(IN_BSTR aName, BandwidthGroupType_T aType, ULONG aMaxMbPerSec)
+STDMETHODIMP BandwidthControl::CreateBandwidthGroup(IN_BSTR aName, BandwidthGroupType_T aType, LONG64 aMaxBytesPerSec)
{
+ if (aMaxBytesPerSec < 0)
+ return setError(E_INVALIDARG,
+ tr("Bandwidth group limit cannot be negative"));
+
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -431,7 +435,7 @@ STDMETHODIMP BandwidthControl::CreateBandwidthGroup(IN_BSTR aName, BandwidthGrou
group.createObject();
- rc = group->init(this, aName, aType, aMaxMbPerSec);
+ rc = group->init(this, aName, aType, aMaxBytesPerSec);
if (FAILED(rc)) return rc;
m->pParent->setModified(Machine::IsModified_BandwidthControl);
@@ -471,7 +475,7 @@ STDMETHODIMP BandwidthControl::DeleteBandwidthGroup(IN_BSTR aName)
m->llBandwidthGroups->remove(group);
/* inform the direct session if any */
- alock.leave();
+ alock.release();
//onStorageControllerChange(); @todo
return S_OK;
@@ -524,7 +528,7 @@ STDMETHODIMP BandwidthControl::GetAllBandwidthGroups(ComSafeArrayOut(IBandwidthG
return S_OK;
}
-HRESULT BandwidthControl::loadSettings(const settings::IoSettings &data)
+HRESULT BandwidthControl::loadSettings(const settings::IOSettings &data)
{
HRESULT rc = S_OK;
@@ -536,14 +540,14 @@ HRESULT BandwidthControl::loadSettings(const settings::IoSettings &data)
++it)
{
const settings::BandwidthGroup &gr = *it;
- rc = CreateBandwidthGroup(Bstr(gr.strName).raw(), gr.enmType, gr.cMaxMbPerSec);
+ rc = CreateBandwidthGroup(Bstr(gr.strName).raw(), gr.enmType, gr.cMaxBytesPerSec);
if (FAILED(rc)) break;
}
return rc;
}
-HRESULT BandwidthControl::saveSettings(settings::IoSettings &data)
+HRESULT BandwidthControl::saveSettings(settings::IOSettings &data)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -561,7 +565,7 @@ HRESULT BandwidthControl::saveSettings(settings::IoSettings &data)
group.strName = (*it)->getName();
group.enmType = (*it)->getType();
- group.cMaxMbPerSec = (*it)->getMaxMbPerSec();
+ group.cMaxBytesPerSec = (*it)->getMaxBytesPerSec();
data.llBandwidthGroups.push_back(group);
}
diff --git a/src/VBox/Main/src-server/BandwidthGroupImpl.cpp b/src/VBox/Main/src-server/BandwidthGroupImpl.cpp
index b5dd1087c..aef8f4c14 100644
--- a/src/VBox/Main/src-server/BandwidthGroupImpl.cpp
+++ b/src/VBox/Main/src-server/BandwidthGroupImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2009 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -34,13 +34,13 @@ struct BackupableBandwidthGroupData
{
BackupableBandwidthGroupData()
: enmType(BandwidthGroupType_Null),
- aMaxMbPerSec(0),
+ aMaxBytesPerSec(0),
cReferences(0)
{ }
Utf8Str strName;
BandwidthGroupType_T enmType;
- ULONG aMaxMbPerSec;
+ LONG64 aMaxBytesPerSec;
ULONG cReferences;
};
@@ -86,7 +86,7 @@ void BandwidthGroup::FinalRelease()
HRESULT BandwidthGroup::init(BandwidthControl *aParent,
const Utf8Str &aName,
BandwidthGroupType_T aType,
- ULONG aMaxMbPerSec)
+ LONG64 aMaxBytesPerSec)
{
LogFlowThisFunc(("aParent=%p aName=\"%s\"\n",
aParent, aName.c_str()));
@@ -110,7 +110,7 @@ HRESULT BandwidthGroup::init(BandwidthControl *aParent,
m->bd->strName = aName;
m->bd->enmType = aType;
m->bd->cReferences = 0;
- m->bd->aMaxMbPerSec = aMaxMbPerSec;
+ m->bd->aMaxBytesPerSec = aMaxBytesPerSec;
/* Confirm a successful initialization */
autoInitSpan.setSucceeded();
@@ -267,33 +267,37 @@ STDMETHODIMP BandwidthGroup::COMGETTER(Reference)(ULONG *aReferences)
return S_OK;
}
-STDMETHODIMP BandwidthGroup::COMGETTER(MaxMbPerSec)(ULONG *aMaxMbPerSec)
+STDMETHODIMP BandwidthGroup::COMGETTER(MaxBytesPerSec)(LONG64 *aMaxBytesPerSec)
{
- CheckComArgOutPointerValid(aMaxMbPerSec);
+ CheckComArgOutPointerValid(aMaxBytesPerSec);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aMaxMbPerSec = m->bd->aMaxMbPerSec;
+ *aMaxBytesPerSec = m->bd->aMaxBytesPerSec;
return S_OK;
}
-STDMETHODIMP BandwidthGroup::COMSETTER(MaxMbPerSec)(ULONG aMaxMbPerSec)
+STDMETHODIMP BandwidthGroup::COMSETTER(MaxBytesPerSec)(LONG64 aMaxBytesPerSec)
{
+ if (aMaxBytesPerSec < 0)
+ return setError(E_INVALIDARG,
+ tr("Bandwidth group limit cannot be negative"));
+
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
m->bd.backup();
- m->bd->aMaxMbPerSec = aMaxMbPerSec;
+ m->bd->aMaxBytesPerSec = aMaxBytesPerSec;
/* inform direct session if any. */
ComObjPtr<Machine> pMachine = m->pParent->getMachine();
- alock.leave();
+ alock.release();
pMachine->onBandwidthGroupChange(this);
return S_OK;
@@ -391,9 +395,9 @@ BandwidthGroupType_T BandwidthGroup::getType() const
return m->bd->enmType;
}
-ULONG BandwidthGroup::getMaxMbPerSec() const
+LONG64 BandwidthGroup::getMaxBytesPerSec() const
{
- return m->bd->aMaxMbPerSec;
+ return m->bd->aMaxBytesPerSec;
}
ULONG BandwidthGroup::getReferences() const
diff --git a/src/VBox/Main/src-server/DHCPServerRunner.cpp b/src/VBox/Main/src-server/DHCPServerRunner.cpp
index 5bb58033a..aab7c8a9f 100644
--- a/src/VBox/Main/src-server/DHCPServerRunner.cpp
+++ b/src/VBox/Main/src-server/DHCPServerRunner.cpp
@@ -103,7 +103,9 @@ int DHCPServerRunner::start()
{
if (mOptionEnabled[i])
{
- const ARGDEF * pArgDef = getArgDef((DHCPCFG)i);
+ const ARGDEF *pArgDef = getArgDef((DHCPCFG)i);
+ if (!pArgDef)
+ continue;
args[index++] = pArgDef->Name; // e.g. "--network"
/* value can be null for e.g. --begin-config has no value
diff --git a/src/VBox/Main/src-server/GuestOSTypeImpl.cpp b/src/VBox/Main/src-server/GuestOSTypeImpl.cpp
index bb5308a54..349547176 100644
--- a/src/VBox/Main/src-server/GuestOSTypeImpl.cpp
+++ b/src/VBox/Main/src-server/GuestOSTypeImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -30,10 +30,10 @@ GuestOSType::GuestOSType()
, mHDDSize(0), mMonitorCount(0)
, mNetworkAdapterType(NetworkAdapterType_Am79C973)
, mNumSerialEnabled(0)
- , mDvdStorageControllerType(StorageControllerType_PIIX3)
- , mDvdStorageBusType(StorageBus_IDE)
- , mHdStorageControllerType(StorageControllerType_PIIX3)
- , mHdStorageBusType(StorageBus_IDE)
+ , mDVDStorageControllerType(StorageControllerType_PIIX3)
+ , mDVDStorageBusType(StorageBus_IDE)
+ , mHDStorageControllerType(StorageControllerType_PIIX3)
+ , mHDStorageBusType(StorageBus_IDE)
, mChipsetType(ChipsetType_PIIX3)
, mAudioControllerType(AudioControllerType_AC97)
{
@@ -78,10 +78,10 @@ HRESULT GuestOSType::init(const Global::OSType &ostype)/*const char *aFamilyId,
uint32_t aRAMSize, uint32_t aVRAMSize, uint64_t aHDDSize,
NetworkAdapterType_T aNetworkAdapterType,
uint32_t aNumSerialEnabled,
- StorageControllerType_T aDvdStorageControllerType,
- StorageBus_T aDvdStorageBusType,
- StorageControllerType_T aHdStorageControllerType,
- StorageBus_T aHdStorageBusType,
+ StorageControllerType_T aDVDStorageControllerType,
+ StorageBus_T aDVDStorageBusType,
+ StorageControllerType_T aHDStorageControllerType,
+ StorageBus_T aHDStorageBusType,
ChipsetType_T aChipsetType
AudioControllerType_T aAudioControllerType*/
{
@@ -118,10 +118,10 @@ HRESULT GuestOSType::init(const Global::OSType &ostype)/*const char *aFamilyId,
unconst(mHDDSize) = ostype.recommendedHDD;
unconst(mNetworkAdapterType) = ostype.networkAdapterType;
unconst(mNumSerialEnabled) = ostype.numSerialEnabled;
- unconst(mDvdStorageControllerType) = ostype.dvdStorageControllerType;
- unconst(mDvdStorageBusType) = ostype.dvdStorageBusType;
- unconst(mHdStorageControllerType) = ostype.hdStorageControllerType;
- unconst(mHdStorageBusType) = ostype.hdStorageBusType;
+ unconst(mDVDStorageControllerType) = ostype.dvdStorageControllerType;
+ unconst(mDVDStorageBusType) = ostype.dvdStorageBusType;
+ unconst(mHDStorageControllerType) = ostype.hdStorageControllerType;
+ unconst(mHDStorageBusType) = ostype.hdStorageBusType;
unconst(mChipsetType) = ostype.chipsetType;
unconst(mAudioControllerType) = ostype.audioControllerType;
@@ -263,6 +263,32 @@ STDMETHODIMP GuestOSType::COMGETTER(RecommendedVRAM)(ULONG *aVRAMSize)
return S_OK;
}
+STDMETHODIMP GuestOSType::COMGETTER(Recommended2DVideoAcceleration)(BOOL *aRecommended2DVideoAcceleration)
+{
+ CheckComArgOutPointerValid(aRecommended2DVideoAcceleration);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /* Constant during life time, no need to lock */
+ *aRecommended2DVideoAcceleration = !!(mOSHint & VBOXOSHINT_ACCEL2D);
+
+ return S_OK;
+}
+
+STDMETHODIMP GuestOSType::COMGETTER(Recommended3DAcceleration)(BOOL *aRecommended3DAcceleration)
+{
+ CheckComArgOutPointerValid(aRecommended3DAcceleration);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /* Constant during life time, no need to lock */
+ *aRecommended3DAcceleration = !!(mOSHint & VBOXOSHINT_ACCEL3D);
+
+ return S_OK;
+}
+
STDMETHODIMP GuestOSType::COMGETTER(RecommendedHDD)(LONG64 *aHDDSize)
{
CheckComArgOutPointerValid(aHDDSize);
@@ -289,15 +315,15 @@ STDMETHODIMP GuestOSType::COMGETTER(AdapterType)(NetworkAdapterType_T *aNetworkA
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedPae)(BOOL *aRecommendedPae)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedPAE)(BOOL *aRecommendedPAE)
{
- CheckComArgOutPointerValid(aRecommendedPae);
+ CheckComArgOutPointerValid(aRecommendedPAE);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* recommended PAE is constant during life time, no need to lock */
- *aRecommendedPae = !!(mOSHint & VBOXOSHINT_PAE);
+ *aRecommendedPAE = !!(mOSHint & VBOXOSHINT_PAE);
return S_OK;
}
@@ -318,7 +344,7 @@ STDMETHODIMP GuestOSType::COMGETTER(RecommendedFirmware)(FirmwareType_T *aFirmwa
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedDvdStorageController)(StorageControllerType_T * aStorageControllerType)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedDVDStorageController)(StorageControllerType_T * aStorageControllerType)
{
CheckComArgOutPointerValid(aStorageControllerType);
@@ -326,12 +352,12 @@ STDMETHODIMP GuestOSType::COMGETTER(RecommendedDvdStorageController)(StorageCont
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* storage controller type is constant during life time, no need to lock */
- *aStorageControllerType = mDvdStorageControllerType;
+ *aStorageControllerType = mDVDStorageControllerType;
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedDvdStorageBus)(StorageBus_T * aStorageBusType)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedDVDStorageBus)(StorageBus_T * aStorageBusType)
{
CheckComArgOutPointerValid(aStorageBusType);
@@ -339,12 +365,12 @@ STDMETHODIMP GuestOSType::COMGETTER(RecommendedDvdStorageBus)(StorageBus_T * aSt
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* storage controller type is constant during life time, no need to lock */
- *aStorageBusType = mDvdStorageBusType;
+ *aStorageBusType = mDVDStorageBusType;
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedHdStorageController)(StorageControllerType_T * aStorageControllerType)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedHDStorageController)(StorageControllerType_T * aStorageControllerType)
{
CheckComArgOutPointerValid(aStorageControllerType);
@@ -352,12 +378,12 @@ STDMETHODIMP GuestOSType::COMGETTER(RecommendedHdStorageController)(StorageContr
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* storage controller type is constant during life time, no need to lock */
- *aStorageControllerType = mHdStorageControllerType;
+ *aStorageControllerType = mHDStorageControllerType;
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedHdStorageBus)(StorageBus_T * aStorageBusType)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedHDStorageBus)(StorageBus_T * aStorageBusType)
{
CheckComArgOutPointerValid(aStorageBusType);
@@ -365,59 +391,59 @@ STDMETHODIMP GuestOSType::COMGETTER(RecommendedHdStorageBus)(StorageBus_T * aSto
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* storage controller type is constant during life time, no need to lock */
- *aStorageBusType = mHdStorageBusType;
+ *aStorageBusType = mHDStorageBusType;
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedUsbHid)(BOOL *aRecommendedUsbHid)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedUSBHID)(BOOL *aRecommendedUSBHID)
{
- CheckComArgOutPointerValid(aRecommendedUsbHid);
+ CheckComArgOutPointerValid(aRecommendedUSBHID);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* HID type is constant during life time, no need to lock */
- *aRecommendedUsbHid = !!(mOSHint & VBOXOSHINT_USBHID);
+ *aRecommendedUSBHID = !!(mOSHint & VBOXOSHINT_USBHID);
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedHpet)(BOOL *aRecommendedHpet)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedHPET)(BOOL *aRecommendedHPET)
{
- CheckComArgOutPointerValid(aRecommendedHpet);
+ CheckComArgOutPointerValid(aRecommendedHPET);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* HPET recommendation is constant during life time, no need to lock */
- *aRecommendedHpet = !!(mOSHint & VBOXOSHINT_HPET);
+ *aRecommendedHPET = !!(mOSHint & VBOXOSHINT_HPET);
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedUsbTablet)(BOOL *aRecommendedUsbTablet)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedUSBTablet)(BOOL *aRecommendedUSBTablet)
{
- CheckComArgOutPointerValid(aRecommendedUsbTablet);
+ CheckComArgOutPointerValid(aRecommendedUSBTablet);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* HID type is constant during life time, no need to lock */
- *aRecommendedUsbTablet = !!(mOSHint & VBOXOSHINT_USBTABLET);
+ *aRecommendedUSBTablet = !!(mOSHint & VBOXOSHINT_USBTABLET);
return S_OK;
}
-STDMETHODIMP GuestOSType::COMGETTER(RecommendedRtcUseUtc)(BOOL *aRecommendedRtcUseUtc)
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedRTCUseUTC)(BOOL *aRecommendedRTCUseUTC)
{
- CheckComArgOutPointerValid(aRecommendedRtcUseUtc);
+ CheckComArgOutPointerValid(aRecommendedRTCUseUTC);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* HID type is constant during life time, no need to lock */
- *aRecommendedRtcUseUtc = !!(mOSHint & VBOXOSHINT_RTCUTC);
+ /* Value is constant during life time, no need to lock */
+ *aRecommendedRTCUseUTC = !!(mOSHint & VBOXOSHINT_RTCUTC);
return S_OK;
}
@@ -447,4 +473,30 @@ STDMETHODIMP GuestOSType::COMGETTER(RecommendedAudioController) (AudioController
return S_OK;
}
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedFloppy)(BOOL *aRecommendedFloppy)
+{
+ CheckComArgOutPointerValid(aRecommendedFloppy);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /* Value is constant during life time, no need to lock */
+ *aRecommendedFloppy = !!(mOSHint & VBOXOSHINT_FLOPPY);
+
+ return S_OK;
+}
+
+STDMETHODIMP GuestOSType::COMGETTER(RecommendedUSB)(BOOL *aRecommendedUSB)
+{
+ CheckComArgOutPointerValid(aRecommendedUSB);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /* Value is constant during life time, no need to lock */
+ *aRecommendedUSB = !(mOSHint & VBOXOSHINT_NOUSB);
+
+ return S_OK;
+}
+
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/src-server/HostImpl.cpp b/src/VBox/Main/src-server/HostImpl.cpp
index 559bbf4e1..295295949 100644
--- a/src/VBox/Main/src-server/HostImpl.cpp
+++ b/src/VBox/Main/src-server/HostImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2004-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -172,19 +172,15 @@ struct Host::Data
{
Data()
:
-#ifdef VBOX_WITH_USB
- usbListsLock(LOCKCLASS_USBLIST),
-#endif
- drivesLock(LOCKCLASS_LISTOFMEDIA),
fDVDDrivesListBuilt(false),
fFloppyDrivesListBuilt(false)
{};
VirtualBox *pParent;
-#ifdef VBOX_WITH_USB
- WriteLockHandle usbListsLock; // protects the below two lists
+ HostNetworkInterfaceList llNetIfs; // list of network interfaces
+#ifdef VBOX_WITH_USB
USBDeviceFilterList llChildren; // all USB device filters
USBDeviceFilterList llUSBDeviceFilters; // USB device filters in use by the USB proxy service
@@ -192,8 +188,8 @@ struct Host::Data
USBProxyService *pUSBProxyService;
#endif /* VBOX_WITH_USB */
- // list of host drives; lazily created by getDVDDrives() and getFloppyDrives()
- WriteLockHandle drivesLock; // protects the below two lists and the bools
+ // list of host drives; lazily created by getDVDDrives() and getFloppyDrives(),
+ // and protected by the medium tree lock handle (including the bools).
MediaList llDVDDrives,
llFloppyDrives;
bool fDVDDrivesListBuilt,
@@ -277,6 +273,8 @@ HRESULT Host::init(VirtualBox *aParent)
#ifdef VBOX_WITH_RESOURCE_USAGE_API
registerMetrics(aParent->performanceCollector());
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
+ /* Create the list of network interfaces so their metrics get registered. */
+ updateNetIfList();
#if defined (RT_OS_WINDOWS)
m->pHostPowerService = new HostPowerServiceWin(m->pParent);
@@ -297,14 +295,14 @@ HRESULT Host::init(VirtualBox *aParent)
uint32_t u32FeaturesECX;
uint32_t u32Dummy;
uint32_t u32FeaturesEDX;
- uint32_t u32VendorEBX, u32VendorECX, u32VendorEDX, u32AMDFeatureEDX, u32AMDFeatureECX;
+ uint32_t u32VendorEBX, u32VendorECX, u32VendorEDX, u32ExtFeatureEDX, u32ExtFeatureECX;
ASMCpuId(0, &u32Dummy, &u32VendorEBX, &u32VendorECX, &u32VendorEDX);
ASMCpuId(1, &u32Dummy, &u32Dummy, &u32FeaturesECX, &u32FeaturesEDX);
- /* Query AMD features. */
- ASMCpuId(0x80000001, &u32Dummy, &u32Dummy, &u32AMDFeatureECX, &u32AMDFeatureEDX);
+ /* Query Extended features. */
+ ASMCpuId(0x80000001, &u32Dummy, &u32Dummy, &u32ExtFeatureECX, &u32ExtFeatureEDX);
- m->fLongModeSupported = !!(u32AMDFeatureEDX & X86_CPUID_AMD_FEATURE_EDX_LONG_MODE);
+ m->fLongModeSupported = !!(u32ExtFeatureEDX & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE);
m->fPAESupported = !!(u32FeaturesEDX & X86_CPUID_FEATURE_EDX_PAE);
if ( u32VendorEBX == X86_CPUID_VENDOR_INTEL_EBX
@@ -312,6 +310,7 @@ HRESULT Host::init(VirtualBox *aParent)
&& u32VendorEDX == X86_CPUID_VENDOR_INTEL_EDX
)
{
+ /* Intel. */
if ( (u32FeaturesECX & X86_CPUID_FEATURE_ECX_VMX)
&& (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
&& (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
@@ -328,7 +327,8 @@ HRESULT Host::init(VirtualBox *aParent)
&& u32VendorEDX == X86_CPUID_VENDOR_AMD_EDX
)
{
- if ( (u32AMDFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
+ /* AMD. */
+ if ( (u32ExtFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
&& (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
&& (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
)
@@ -343,6 +343,23 @@ HRESULT Host::init(VirtualBox *aParent)
m->fNestedPagingSupported = true;
}
}
+ else
+ if ( u32VendorEBX == X86_CPUID_VENDOR_VIA_EBX
+ && u32VendorECX == X86_CPUID_VENDOR_VIA_ECX
+ && u32VendorEDX == X86_CPUID_VENDOR_VIA_EDX
+ )
+ {
+ /* VIA. */
+ if ( (u32FeaturesECX & X86_CPUID_FEATURE_ECX_VMX)
+ && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
+ && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
+ )
+ {
+ int rc = SUPR3QueryVTxSupported();
+ if (RT_SUCCESS(rc))
+ m->fVTSupported = true;
+ }
+ }
}
#if 0 /* needs testing */
@@ -398,7 +415,7 @@ HRESULT Host::init(VirtualBox *aParent)
progress.asOutParam(),
it->c_str());
if (RT_FAILURE(r))
- return E_FAIL;
+ LogRel(("failed to create %s, error (0x%x)\n", it->c_str(), r));
}
#endif /* defined (RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) */
@@ -423,8 +440,15 @@ void Host::uninit()
return;
#ifdef VBOX_WITH_RESOURCE_USAGE_API
- unregisterMetrics (m->pParent->performanceCollector());
+ PerformanceCollector *aCollector = m->pParent->performanceCollector();
+ unregisterMetrics (aCollector);
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
+ /*
+ * Note that unregisterMetrics() has unregistered all metrics associated
+ * with Host including network interface ones. We can destroy network
+ * interface objects now.
+ */
+ m->llNetIfs.clear();
#ifdef VBOX_WITH_USB
/* wait for USB proxy service to terminate before we uninit all USB
@@ -472,7 +496,7 @@ STDMETHODIMP Host::COMGETTER(DVDDrives)(ComSafeArrayOut(IMedium *, aDrives))
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoWriteLock alock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
MediaList *pList;
HRESULT rc = getDrives(DeviceType_DVD, true /* fRefresh */, pList);
@@ -498,7 +522,7 @@ STDMETHODIMP Host::COMGETTER(FloppyDrives)(ComSafeArrayOut(IMedium *, aDrives))
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoWriteLock alock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
MediaList *pList;
HRESULT rc = getDrives(DeviceType_Floppy, true /* fRefresh */, pList);
@@ -537,7 +561,7 @@ static int vboxNetWinAddComponent(std::list< ComObjPtr<HostNetworkInterface> > *
ComObjPtr<HostNetworkInterface> iface;
iface.createObject();
/* remove the curly bracket at the end */
- if (SUCCEEDED(iface->init (name, Guid (IfGuid), HostNetworkInterfaceType_Bridged)))
+ if (SUCCEEDED(iface->init (name, name, Guid (IfGuid), HostNetworkInterfaceType_Bridged)))
{
// iface->setVirtualBox(m->pParent);
pPist->push_back(iface);
@@ -570,15 +594,21 @@ STDMETHODIMP Host::COMGETTER(NetworkInterfaces)(ComSafeArrayOut(IHostNetworkInte
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- std::list<ComObjPtr<HostNetworkInterface> > list;
-
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
# ifdef VBOX_WITH_HOSTNETIF_API
- int rc = NetIfList(list);
+ int rc = updateNetIfList();
if (rc)
{
Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
}
+
+ SafeIfaceArray<IHostNetworkInterface> networkInterfaces (m->llNetIfs);
+ networkInterfaces.detachTo(ComSafeArrayOutArg(aNetworkInterfaces));
+
+ return S_OK;
+
# else
+ std::list<ComObjPtr<HostNetworkInterface> > list;
# if defined(RT_OS_DARWIN)
PDARWINETHERNIC pEtherNICs = DarwinGetEthernetControllers();
@@ -686,7 +716,7 @@ STDMETHODIMP Host::COMGETTER(NetworkInterfaces)(ComSafeArrayOut(IHostNetworkInte
}
else
{
- LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)", hr));
+ LogRel(("failed to get the sun_VBoxNetFlt component, error (0x%x)\n", hr));
}
VBoxNetCfgWinReleaseINetCfg(pNc, FALSE);
@@ -725,19 +755,13 @@ STDMETHODIMP Host::COMGETTER(NetworkInterfaces)(ComSafeArrayOut(IHostNetworkInte
close(sock);
}
# endif /* RT_OS_LINUX */
-# endif
-
- std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
- for (it = list.begin(); it != list.end(); ++it)
- {
- (*it)->setVirtualBox(m->pParent);
- }
SafeIfaceArray<IHostNetworkInterface> networkInterfaces (list);
networkInterfaces.detachTo(ComSafeArrayOutArg(aNetworkInterfaces));
return S_OK;
+# endif
#else
/* Not implemented / supported on this platform. */
ReturnComNotImplemented();
@@ -779,7 +803,7 @@ STDMETHODIMP Host::COMGETTER(USBDeviceFilters)(ComSafeArrayOut(IHostUSBDeviceFil
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = checkUSBProxyService();
if (FAILED(rc)) return rc;
@@ -1136,10 +1160,9 @@ STDMETHODIMP Host::CreateHostOnlyNetworkInterface(IHostNetworkInterface **aHostN
tmpMask.raw());
ComAssertComRCRet(hrc, hrc);
#endif
- return S_OK;
}
- return r == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
+ return S_OK;
#else
return E_NOTIMPL;
#endif
@@ -1230,7 +1253,7 @@ STDMETHODIMP Host::InsertUSBDeviceFilter(ULONG aPosition,
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
clearError();
MultiResult rc = checkUSBProxyService();
@@ -1292,7 +1315,7 @@ STDMETHODIMP Host::RemoveUSBDeviceFilter(ULONG aPosition)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
clearError();
MultiResult rc = checkUSBProxyService();
@@ -1378,17 +1401,18 @@ STDMETHODIMP Host::FindHostNetworkInterfaceByName(IN_BSTR name, IHostNetworkInte
if (!networkInterface)
return E_POINTER;
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
*networkInterface = NULL;
ComObjPtr<HostNetworkInterface> found;
- std::list <ComObjPtr<HostNetworkInterface> > list;
- int rc = NetIfList(list);
+ int rc = updateNetIfList();
if (RT_FAILURE(rc))
{
Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
return E_FAIL;
}
- std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
- for (it = list.begin(); it != list.end(); ++it)
+ HostNetworkInterfaceList::iterator it;
+ for (it = m->llNetIfs.begin(); it != m->llNetIfs.end(); ++it)
{
Bstr n;
(*it)->COMGETTER(Name) (n.asOutParam());
@@ -1400,8 +1424,6 @@ STDMETHODIMP Host::FindHostNetworkInterfaceByName(IN_BSTR name, IHostNetworkInte
return setError(E_INVALIDARG,
HostNetworkInterface::tr("The host network interface with the given name could not be found"));
- found->setVirtualBox(m->pParent);
-
return found.queryInterfaceTo(networkInterface);
#endif
}
@@ -1416,17 +1438,18 @@ STDMETHODIMP Host::FindHostNetworkInterfaceById(IN_BSTR id, IHostNetworkInterfac
if (!networkInterface)
return E_POINTER;
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
*networkInterface = NULL;
ComObjPtr<HostNetworkInterface> found;
- std::list <ComObjPtr<HostNetworkInterface> > list;
- int rc = NetIfList(list);
+ int rc = updateNetIfList();
if (RT_FAILURE(rc))
{
Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
return E_FAIL;
}
- std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
- for (it = list.begin(); it != list.end(); ++it)
+ HostNetworkInterfaceList::iterator it;
+ for (it = m->llNetIfs.begin(); it != m->llNetIfs.end(); ++it)
{
Bstr g;
(*it)->COMGETTER(Id) (g.asOutParam());
@@ -1438,8 +1461,6 @@ STDMETHODIMP Host::FindHostNetworkInterfaceById(IN_BSTR id, IHostNetworkInterfac
return setError(E_INVALIDARG,
HostNetworkInterface::tr("The host network interface with the given GUID could not be found"));
- found->setVirtualBox(m->pParent);
-
return found.queryInterfaceTo(networkInterface);
#endif
}
@@ -1448,15 +1469,16 @@ STDMETHODIMP Host::FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_T ty
ComSafeArrayOut(IHostNetworkInterface *, aNetworkInterfaces))
{
#ifdef VBOX_WITH_HOSTNETIF_API
- std::list <ComObjPtr<HostNetworkInterface> > allList;
- int rc = NetIfList(allList);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ int rc = updateNetIfList();
if (RT_FAILURE(rc))
return E_FAIL;
- std::list <ComObjPtr<HostNetworkInterface> > resultList;
+ HostNetworkInterfaceList resultList;
- std::list <ComObjPtr<HostNetworkInterface> >::iterator it;
- for (it = allList.begin(); it != allList.end(); ++it)
+ HostNetworkInterfaceList::iterator it;
+ for (it = m->llNetIfs.begin(); it != m->llNetIfs.end(); ++it)
{
HostNetworkInterfaceType_T t;
HRESULT hr = (*it)->COMGETTER(InterfaceType)(&t);
@@ -1464,10 +1486,7 @@ STDMETHODIMP Host::FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_T ty
return hr;
if (t == type)
- {
- (*it)->setVirtualBox(m->pParent);
resultList.push_back (*it);
- }
}
SafeIfaceArray<IHostNetworkInterface> filteredNetworkInterfaces (resultList);
@@ -1569,7 +1588,7 @@ HRESULT Host::loadSettings(const settings::Host &data)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoMultiWriteLock2 alock(this->lockHandle(), &m->usbListsLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
for (settings::USBDeviceFiltersList::const_iterator it = data.llUSBDeviceFilters.begin();
it != data.llUSBDeviceFilters.end();
@@ -1603,8 +1622,7 @@ HRESULT Host::saveSettings(settings::Host &data)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoReadLock alock1(this COMMA_LOCKVAL_SRC_POS);
- AutoReadLock alock2(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
data.llUSBDeviceFilters.clear();
@@ -1632,7 +1650,7 @@ HRESULT Host::saveSettings(settings::Host &data)
* This builds the list on the first call; it adds or removes host drives
* that may have changed if fRefresh == true.
*
- * The caller must hold the m->drivesLock write lock before calling this.
+ * The caller must hold the medium tree write lock before calling this.
* To protect the list to which the caller's pointer points, the caller
* must also hold that lock.
*
@@ -1646,7 +1664,7 @@ HRESULT Host::getDrives(DeviceType_T mediumType,
MediaList *&pll)
{
HRESULT rc = S_OK;
- Assert(m->drivesLock.isWriteLockOnCurrentThread());
+ Assert(m->pParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
MediaList llNew;
MediaList *pllCached;
@@ -1771,7 +1789,7 @@ HRESULT Host::findHostDriveById(DeviceType_T mediumType,
{
MediaList *pllMedia;
- AutoWriteLock wlock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock wlock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
HRESULT rc = getDrives(mediumType, fRefresh, pllMedia);
if (SUCCEEDED(rc))
{
@@ -1811,7 +1829,7 @@ HRESULT Host::findHostDriveByName(DeviceType_T mediumType,
{
MediaList *pllMedia;
- AutoWriteLock wlock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock wlock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
HRESULT rc = getDrives(mediumType, fRefresh, pllMedia);
if (SUCCEEDED(rc))
{
@@ -1847,7 +1865,7 @@ HRESULT Host::findHostDriveByNameOrId(DeviceType_T mediumType,
const Utf8Str &strNameOrId,
ComObjPtr<Medium> &pMedium)
{
- AutoWriteLock wlock(m->drivesLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock wlock(m->pParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
Guid uuid(strNameOrId);
if (!uuid.isEmpty())
@@ -1866,7 +1884,7 @@ HRESULT Host::buildDVDDrivesList(MediaList &list)
{
HRESULT rc = S_OK;
- Assert(m->drivesLock.isWriteLockOnCurrentThread());
+ Assert(m->pParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
try
{
@@ -1948,7 +1966,7 @@ HRESULT Host::buildFloppyDrivesList(MediaList &list)
{
HRESULT rc = S_OK;
- Assert(m->drivesLock.isWriteLockOnCurrentThread());
+ Assert(m->pParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
try
{
@@ -2011,7 +2029,7 @@ HRESULT Host::addChild(HostUSBDeviceFilter *pChild)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoWriteLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
m->llChildren.push_back(pChild);
@@ -2023,7 +2041,7 @@ HRESULT Host::removeChild(HostUSBDeviceFilter *pChild)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- AutoWriteLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
for (USBDeviceFilterList::iterator it = m->llChildren.begin();
it != m->llChildren.end();
@@ -2103,7 +2121,7 @@ HRESULT Host::onUSBDeviceFilterChange(HostUSBDeviceFilter *aFilter,
*/
void Host::getUSBFilters(Host::USBDeviceFilterList *aGlobalFilters)
{
- AutoReadLock alock(&m->usbListsLock COMMA_LOCKVAL_SRC_POS);
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
*aGlobalFilters = m->llUSBDeviceFilters;
}
@@ -2799,8 +2817,154 @@ HRESULT Host::checkUSBProxyService()
}
#endif /* VBOX_WITH_USB */
+HRESULT Host::updateNetIfList()
+{
+#ifdef VBOX_WITH_HOSTNETIF_API
+ AssertReturn(AutoCaller(this).state() == InInit ||
+ isWriteLockOnCurrentThread(), E_FAIL);
+
+ HostNetworkInterfaceList list, listCopy;
+ int rc = NetIfList(list);
+ if (rc)
+ {
+ Log(("Failed to get host network interface list with rc=%Rrc\n", rc));
+ return E_FAIL;
+ }
+ AssertReturn(m->pParent, E_FAIL);
+ /* Make a copy as the original may be partially destroyed later. */
+ listCopy = list;
+ HostNetworkInterfaceList::iterator itOld, itNew;
+ PerformanceCollector *aCollector = m->pParent->performanceCollector();
+ for (itOld = m->llNetIfs.begin(); itOld != m->llNetIfs.end(); ++itOld)
+ {
+ bool fGone = true;
+ Bstr nameOld;
+ (*itOld)->COMGETTER(Name) (nameOld.asOutParam());
+ for (itNew = listCopy.begin(); itNew != listCopy.end(); ++itNew)
+ {
+ Bstr nameNew;
+ (*itNew)->COMGETTER(Name) (nameNew.asOutParam());
+ if (nameNew == nameOld)
+ {
+ fGone = false;
+ listCopy.erase(itNew);
+ break;
+ }
+ }
+ if (fGone)
+ (*itOld)->unregisterMetrics(aCollector, this);
+ }
+ /*
+ * Need to set the references to VirtualBox object in all interface objects
+ * (see @bugref{6439}).
+ */
+ for (itNew = list.begin(); itNew != list.end(); ++itNew)
+ (*itNew)->setVirtualBox(m->pParent);
+ /* At this point listCopy will contain newly discovered interfaces only. */
+ for (itNew = listCopy.begin(); itNew != listCopy.end(); ++itNew)
+ {
+ HostNetworkInterfaceType_T t;
+ HRESULT hr = (*itNew)->COMGETTER(InterfaceType)(&t);
+ if (FAILED(hr))
+ {
+ Bstr n;
+ (*itNew)->COMGETTER(Name) (n.asOutParam());
+ LogRel(("Host::updateNetIfList: failed to get interface type for %ls\n", n.raw()));
+ }
+ else if (t == HostNetworkInterfaceType_Bridged)
+ (*itNew)->registerMetrics(aCollector, this);
+ }
+ m->llNetIfs = list;
+ return S_OK;
+#else
+ return E_NOTIMPL;
+#endif
+}
+
#ifdef VBOX_WITH_RESOURCE_USAGE_API
+void Host::registerDiskMetrics(PerformanceCollector *aCollector)
+{
+ pm::CollectorHAL *hal = aCollector->getHAL();
+ /* Create sub metrics */
+ Utf8StrFmt fsNameBase("FS/{%s}/Usage", "/");
+ //Utf8StrFmt fsNameBase("Filesystem/[root]/Usage");
+ pm::SubMetric *fsRootUsageTotal = new pm::SubMetric(fsNameBase + "/Total",
+ "Root file system size.");
+ pm::SubMetric *fsRootUsageUsed = new pm::SubMetric(fsNameBase + "/Used",
+ "Root file system space currently occupied.");
+ pm::SubMetric *fsRootUsageFree = new pm::SubMetric(fsNameBase + "/Free",
+ "Root file system space currently empty.");
+
+ pm::BaseMetric *fsRootUsage = new pm::HostFilesystemUsage(hal, this,
+ fsNameBase, "/",
+ fsRootUsageTotal,
+ fsRootUsageUsed,
+ fsRootUsageFree);
+ aCollector->registerBaseMetric (fsRootUsage);
+
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal, 0));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageTotal,
+ new pm::AggregateMax()));
+
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed, 0));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageUsed,
+ new pm::AggregateMax()));
+
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree, 0));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(fsRootUsage, fsRootUsageFree,
+ new pm::AggregateMax()));
+
+ /* For now we are concerned with the root file system only. */
+ pm::DiskList disks;
+ int rc = hal->getDiskListByFs("/", disks);
+ if (RT_FAILURE(rc) || disks.empty())
+ return;
+ pm::DiskList::iterator it;
+ for (it = disks.begin(); it != disks.end(); ++it)
+ {
+ Utf8StrFmt strName("Disk/%s", it->c_str());
+ pm::SubMetric *fsLoadUtil = new pm::SubMetric(strName + "/Load/Util",
+ "Percentage of time disk was busy serving I/O requests.");
+ pm::SubMetric *fsUsageTotal = new pm::SubMetric(strName + "/Usage/Total",
+ "Disk size.");
+ pm::BaseMetric *fsLoad = new pm::HostDiskLoadRaw(hal, this, strName + "/Load",
+ *it, fsLoadUtil);
+ aCollector->registerBaseMetric (fsLoad);
+ pm::BaseMetric *fsUsage = new pm::HostDiskUsage(hal, this, strName + "/Usage",
+ *it, fsUsageTotal);
+ aCollector->registerBaseMetric (fsUsage);
+
+ aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil, 0));
+ aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(fsLoad, fsLoadUtil,
+ new pm::AggregateMax()));
+
+ aCollector->registerMetric(new pm::Metric(fsUsage, fsUsageTotal, 0));
+ aCollector->registerMetric(new pm::Metric(fsUsage, fsUsageTotal,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(fsUsage, fsUsageTotal,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(fsUsage, fsUsageTotal,
+ new pm::AggregateMax()));
+ }
+}
+
void Host::registerMetrics(PerformanceCollector *aCollector)
{
pm::CollectorHAL *hal = aCollector->getHAL();
@@ -2830,20 +2994,17 @@ void Host::registerMetrics(PerformanceCollector *aCollector)
/* Create and register base metrics */
- IUnknown *objptr;
- ComObjPtr<Host> tmp = this;
- tmp.queryInterfaceTo(&objptr);
- pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw(hal, objptr, cpuLoadUser, cpuLoadKernel,
+ pm::BaseMetric *cpuLoad = new pm::HostCpuLoadRaw(hal, this, cpuLoadUser, cpuLoadKernel,
cpuLoadIdle);
aCollector->registerBaseMetric (cpuLoad);
- pm::BaseMetric *cpuMhz = new pm::HostCpuMhz(hal, objptr, cpuMhzSM);
+ pm::BaseMetric *cpuMhz = new pm::HostCpuMhz(hal, this, cpuMhzSM);
aCollector->registerBaseMetric (cpuMhz);
- pm::BaseMetric *ramUsage = new pm::HostRamUsage(hal, objptr,
+ pm::BaseMetric *ramUsage = new pm::HostRamUsage(hal, this,
ramUsageTotal,
ramUsageUsed,
ramUsageFree);
aCollector->registerBaseMetric (ramUsage);
- pm::BaseMetric *ramVmm = new pm::HostRamVmm(aCollector->getGuestManager(), objptr,
+ pm::BaseMetric *ramVmm = new pm::HostRamVmm(aCollector->getGuestManager(), this,
ramVMMUsed,
ramVMMFree,
ramVMMBallooned,
@@ -2937,6 +3098,7 @@ void Host::registerMetrics(PerformanceCollector *aCollector)
new pm::AggregateMin()));
aCollector->registerMetric(new pm::Metric(ramVmm, ramVMMShared,
new pm::AggregateMax()));
+ registerDiskMetrics(aCollector);
}
void Host::unregisterMetrics (PerformanceCollector *aCollector)
diff --git a/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp b/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp
index 8b35e27f9..61a8a61fd 100644
--- a/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp
+++ b/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2006-2008 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -21,6 +21,8 @@
#include "AutoCaller.h"
#include "Logging.h"
#include "netif.h"
+#include "Performance.h"
+#include "PerformanceImpl.h"
#include <iprt/cpp/utils.h>
@@ -47,7 +49,7 @@ HRESULT HostNetworkInterface::FinalConstruct()
void HostNetworkInterface::FinalRelease()
{
- uninit ();
+ uninit();
BaseFinalRelease();
}
@@ -61,7 +63,7 @@ void HostNetworkInterface::FinalRelease()
* @param aInterfaceName name of the network interface
* @param aGuid GUID of the host network interface
*/
-HRESULT HostNetworkInterface::init(Bstr aInterfaceName, Guid aGuid, HostNetworkInterfaceType_T ifType)
+HRESULT HostNetworkInterface::init(Bstr aInterfaceName, Bstr aShortName, Guid aGuid, HostNetworkInterfaceType_T ifType)
{
LogFlowThisFunc(("aInterfaceName={%ls}, aGuid={%s}\n",
aInterfaceName.raw(), aGuid.toString().c_str()));
@@ -74,6 +76,7 @@ HRESULT HostNetworkInterface::init(Bstr aInterfaceName, Guid aGuid, HostNetworkI
AssertReturn(autoInitSpan.isOk(), E_FAIL);
unconst(mInterfaceName) = aInterfaceName;
+ unconst(mNetworkName) = composeNetworkName(aShortName);
unconst(mGuid) = aGuid;
mIfType = ifType;
@@ -83,9 +86,63 @@ HRESULT HostNetworkInterface::init(Bstr aInterfaceName, Guid aGuid, HostNetworkI
return S_OK;
}
+void HostNetworkInterface::registerMetrics(PerformanceCollector *aCollector, ComPtr<IUnknown> objptr)
+{
+ LogFlowThisFunc(("mShortName={%ls}, mInterfaceName={%ls}, mGuid={%s}, mSpeedMbits=%u\n",
+ mShortName.raw(), mInterfaceName.raw(), mGuid.toString().c_str(), m.speedMbits));
+ pm::CollectorHAL *hal = aCollector->getHAL();
+ /* Create sub metrics */
+ Utf8StrFmt strName("Net/%ls", mShortName.raw());
+ pm::SubMetric *networkLoadRx = new pm::SubMetric(strName + "/Load/Rx",
+ "Percentage of network interface receive bandwidth used.");
+ pm::SubMetric *networkLoadTx = new pm::SubMetric(strName + "/Load/Tx",
+ "Percentage of network interface transmit bandwidth used.");
+ pm::SubMetric *networkLinkSpeed = new pm::SubMetric(strName + "/LinkSpeed",
+ "Physical link speed.");
+
+ /* Create and register base metrics */
+ pm::BaseMetric *networkSpeed = new pm::HostNetworkSpeed(hal, objptr, strName + "/LinkSpeed", Utf8Str(mShortName), Utf8Str(mInterfaceName), m.speedMbits, networkLinkSpeed);
+ aCollector->registerBaseMetric(networkSpeed);
+ pm::BaseMetric *networkLoad = new pm::HostNetworkLoadRaw(hal, objptr, strName + "/Load", Utf8Str(mShortName), Utf8Str(mInterfaceName), m.speedMbits, networkLoadRx, networkLoadTx);
+ aCollector->registerBaseMetric(networkLoad);
+
+ aCollector->registerMetric(new pm::Metric(networkSpeed, networkLinkSpeed, 0));
+ aCollector->registerMetric(new pm::Metric(networkSpeed, networkLinkSpeed,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(networkSpeed, networkLinkSpeed,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(networkSpeed, networkLinkSpeed,
+ new pm::AggregateMax()));
+
+ aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadRx, 0));
+ aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadRx,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadRx,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadRx,
+ new pm::AggregateMax()));
+
+ aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadTx, 0));
+ aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadTx,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadTx,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(networkLoad, networkLoadTx,
+ new pm::AggregateMax()));
+}
+
+void HostNetworkInterface::unregisterMetrics(PerformanceCollector *aCollector, ComPtr<IUnknown> objptr)
+{
+ LogFlowThisFunc(("mShortName={%ls}, mInterfaceName={%ls}, mGuid={%s}\n",
+ mShortName.raw(), mInterfaceName.raw(), mGuid.toString().c_str()));
+ Utf8StrFmt name("Net/%ls", mShortName.raw());
+ aCollector->unregisterMetricsFor(objptr, name + "/*");
+ aCollector->unregisterBaseMetricsFor(objptr, name);
+}
+
#ifdef VBOX_WITH_HOSTNETIF_API
-HRESULT HostNetworkInterface::updateConfig ()
+HRESULT HostNetworkInterface::updateConfig()
{
NETIFINFO info;
int rc = NetIfGetConfig(this, &info);
@@ -103,13 +160,17 @@ HRESULT HostNetworkInterface::updateConfig ()
#else /* !RT_OS_WINDOWS */
m.mediumType = info.enmMediumType;
m.status = info.enmStatus;
-
#endif /* !RT_OS_WINDOWS */
+ m.speedMbits = info.uSpeedMbits;
return S_OK;
}
return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
}
+Bstr HostNetworkInterface::composeNetworkName(const Utf8Str aShortName)
+{
+ return Utf8Str("HostInterfaceNetworking-").append(aShortName);
+}
/**
* Initializes the host object.
*
@@ -117,7 +178,7 @@ HRESULT HostNetworkInterface::updateConfig ()
* @param aInterfaceName name of the network interface
* @param aGuid GUID of the host network interface
*/
-HRESULT HostNetworkInterface::init (Bstr aInterfaceName, HostNetworkInterfaceType_T ifType, PNETIFINFO pIf)
+HRESULT HostNetworkInterface::init(Bstr aInterfaceName, HostNetworkInterfaceType_T ifType, PNETIFINFO pIf)
{
// LogFlowThisFunc(("aInterfaceName={%ls}, aGuid={%s}\n",
// aInterfaceName.raw(), aGuid.toString().raw()));
@@ -132,6 +193,16 @@ HRESULT HostNetworkInterface::init (Bstr aInterfaceName, HostNetworkInterfaceTyp
unconst(mInterfaceName) = aInterfaceName;
unconst(mGuid) = pIf->Uuid;
+ if (pIf->szShortName[0])
+ {
+ unconst(mNetworkName) = composeNetworkName(pIf->szShortName);
+ unconst(mShortName) = pIf->szShortName;
+ }
+ else
+ {
+ unconst(mNetworkName) = composeNetworkName(aInterfaceName);
+ unconst(mShortName) = aInterfaceName;
+ }
mIfType = ifType;
m.realIPAddress = m.IPAddress = pIf->IPAddress.u;
@@ -147,6 +218,7 @@ HRESULT HostNetworkInterface::init (Bstr aInterfaceName, HostNetworkInterfaceTyp
m.mediumType = pIf->enmMediumType;
m.status = pIf->enmStatus;
#endif /* !RT_OS_WINDOWS */
+ m.speedMbits = pIf->uSpeedMbits;
/* Confirm a successful initialization */
autoInitSpan.setSucceeded();
@@ -164,7 +236,7 @@ HRESULT HostNetworkInterface::init (Bstr aInterfaceName, HostNetworkInterfaceTyp
* @returns COM status code
* @param aInterfaceName address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(Name) (BSTR *aInterfaceName)
+STDMETHODIMP HostNetworkInterface::COMGETTER(Name)(BSTR *aInterfaceName)
{
CheckComArgOutPointerValid(aInterfaceName);
@@ -182,7 +254,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(Name) (BSTR *aInterfaceName)
* @returns COM status code
* @param aGuid address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(Id) (BSTR *aGuid)
+STDMETHODIMP HostNetworkInterface::COMGETTER(Id)(BSTR *aGuid)
{
CheckComArgOutPointerValid(aGuid);
@@ -194,14 +266,14 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(Id) (BSTR *aGuid)
return S_OK;
}
-STDMETHODIMP HostNetworkInterface::COMGETTER(DhcpEnabled) (BOOL *aDhcpEnabled)
+STDMETHODIMP HostNetworkInterface::COMGETTER(DHCPEnabled)(BOOL *aDHCPEnabled)
{
- CheckComArgOutPointerValid(aDhcpEnabled);
+ CheckComArgOutPointerValid(aDHCPEnabled);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- *aDhcpEnabled = m.dhcpEnabled;
+ *aDHCPEnabled = m.dhcpEnabled;
return S_OK;
}
@@ -213,7 +285,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(DhcpEnabled) (BOOL *aDhcpEnabled)
* @returns COM status code
* @param aIPAddress address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(IPAddress) (BSTR *aIPAddress)
+STDMETHODIMP HostNetworkInterface::COMGETTER(IPAddress)(BSTR *aIPAddress)
{
CheckComArgOutPointerValid(aIPAddress);
@@ -242,7 +314,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(IPAddress) (BSTR *aIPAddress)
* @returns COM status code
* @param aNetworkMask address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(NetworkMask) (BSTR *aNetworkMask)
+STDMETHODIMP HostNetworkInterface::COMGETTER(NetworkMask)(BSTR *aNetworkMask)
{
CheckComArgOutPointerValid(aNetworkMask);
@@ -265,7 +337,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(NetworkMask) (BSTR *aNetworkMask)
return E_FAIL;
}
-STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6Supported) (BOOL *aIPV6Supported)
+STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6Supported)(BOOL *aIPV6Supported)
{
CheckComArgOutPointerValid(aIPV6Supported);
#if defined(RT_OS_WINDOWS)
@@ -283,7 +355,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6Supported) (BOOL *aIPV6Supporte
* @returns COM status code
* @param aIPV6Address address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6Address) (BSTR *aIPV6Address)
+STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6Address)(BSTR *aIPV6Address)
{
CheckComArgOutPointerValid(aIPV6Address);
@@ -301,7 +373,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6Address) (BSTR *aIPV6Address)
* @returns COM status code
* @param aIPV6Mask address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6NetworkMaskPrefixLength) (ULONG *aIPV6NetworkMaskPrefixLength)
+STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6NetworkMaskPrefixLength)(ULONG *aIPV6NetworkMaskPrefixLength)
{
CheckComArgOutPointerValid(aIPV6NetworkMaskPrefixLength);
@@ -319,7 +391,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(IPV6NetworkMaskPrefixLength) (ULONG
* @returns COM status code
* @param aHardwareAddress address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(HardwareAddress) (BSTR *aHardwareAddress)
+STDMETHODIMP HostNetworkInterface::COMGETTER(HardwareAddress)(BSTR *aHardwareAddress)
{
CheckComArgOutPointerValid(aHardwareAddress);
@@ -337,7 +409,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(HardwareAddress) (BSTR *aHardwareAd
* @returns COM status code
* @param aType address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(MediumType) (HostNetworkInterfaceMediumType_T *aType)
+STDMETHODIMP HostNetworkInterface::COMGETTER(MediumType)(HostNetworkInterfaceMediumType_T *aType)
{
CheckComArgOutPointerValid(aType);
@@ -355,7 +427,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(MediumType) (HostNetworkInterfaceMe
* @returns COM status code
* @param aStatus address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(Status) (HostNetworkInterfaceStatus_T *aStatus)
+STDMETHODIMP HostNetworkInterface::COMGETTER(Status)(HostNetworkInterfaceStatus_T *aStatus)
{
CheckComArgOutPointerValid(aStatus);
@@ -373,7 +445,7 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(Status) (HostNetworkInterfaceStatus
* @returns COM status code
* @param aType address of result pointer
*/
-STDMETHODIMP HostNetworkInterface::COMGETTER(InterfaceType) (HostNetworkInterfaceType_T *aType)
+STDMETHODIMP HostNetworkInterface::COMGETTER(InterfaceType)(HostNetworkInterfaceType_T *aType)
{
CheckComArgOutPointerValid(aType);
@@ -386,20 +458,19 @@ STDMETHODIMP HostNetworkInterface::COMGETTER(InterfaceType) (HostNetworkInterfac
}
-STDMETHODIMP HostNetworkInterface::COMGETTER(NetworkName) (BSTR *aNetworkName)
+STDMETHODIMP HostNetworkInterface::COMGETTER(NetworkName)(BSTR *aNetworkName)
{
+ CheckComArgOutPointerValid(aNetworkName);
+
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- Utf8Str utf8Name("HostInterfaceNetworking-");
- utf8Name.append(Utf8Str(mInterfaceName)) ;
- Bstr netName(utf8Name);
- netName.detachTo(aNetworkName);
+ mNetworkName.cloneTo(aNetworkName);
return S_OK;
}
-STDMETHODIMP HostNetworkInterface::EnableStaticIpConfig (IN_BSTR aIPAddress, IN_BSTR aNetMask)
+STDMETHODIMP HostNetworkInterface::EnableStaticIPConfig(IN_BSTR aIPAddress, IN_BSTR aNetMask)
{
#ifndef VBOX_WITH_HOSTNETIF_API
return E_NOTIMPL;
@@ -443,9 +514,11 @@ STDMETHODIMP HostNetworkInterface::EnableStaticIpConfig (IN_BSTR aIPAddress, IN_
{
m.realIPAddress = ip;
m.realNetworkMask = mask;
- if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(), Bstr(aIPAddress).raw())))
+ if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(),
+ Bstr(aIPAddress).raw())))
return E_FAIL;
- if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(), Bstr(aNetMask).raw())))
+ if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(),
+ Bstr(aNetMask).raw())))
return E_FAIL;
return S_OK;
}
@@ -461,7 +534,7 @@ STDMETHODIMP HostNetworkInterface::EnableStaticIpConfig (IN_BSTR aIPAddress, IN_
#endif
}
-STDMETHODIMP HostNetworkInterface::EnableStaticIpConfigV6 (IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
+STDMETHODIMP HostNetworkInterface::EnableStaticIPConfigV6(IN_BSTR aIPV6Address, ULONG aIPV6MaskPrefixLength)
{
#ifndef VBOX_WITH_HOSTNETIF_API
return E_NOTIMPL;
@@ -489,7 +562,8 @@ STDMETHODIMP HostNetworkInterface::EnableStaticIpConfigV6 (IN_BSTR aIPV6Address,
{
m.realIPV6Address = aIPV6Address;
m.realIPV6PrefixLength = aIPV6MaskPrefixLength;
- if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(), Bstr(aIPV6Address).raw())))
+ if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(),
+ Bstr(aIPV6Address).raw())))
return E_FAIL;
if (FAILED(mVBox->SetExtraData(BstrFmt("HostOnly/%ls/IPV6NetMask", mInterfaceName.raw()).raw(),
BstrFmt("%u", aIPV6MaskPrefixLength).raw())))
@@ -501,7 +575,7 @@ STDMETHODIMP HostNetworkInterface::EnableStaticIpConfigV6 (IN_BSTR aIPV6Address,
#endif
}
-STDMETHODIMP HostNetworkInterface::EnableDynamicIpConfig ()
+STDMETHODIMP HostNetworkInterface::EnableDynamicIPConfig()
{
#ifndef VBOX_WITH_HOSTNETIF_API
return E_NOTIMPL;
@@ -519,7 +593,7 @@ STDMETHODIMP HostNetworkInterface::EnableDynamicIpConfig ()
#endif
}
-STDMETHODIMP HostNetworkInterface::DhcpRediscover ()
+STDMETHODIMP HostNetworkInterface::DHCPRediscover()
{
#ifndef VBOX_WITH_HOSTNETIF_API
return E_NOTIMPL;
@@ -541,6 +615,8 @@ HRESULT HostNetworkInterface::setVirtualBox(VirtualBox *pVBox)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ AssertReturn(mVBox != pVBox, S_OK);
+
unconst(mVBox) = pVBox;
#if !defined(RT_OS_WINDOWS)
@@ -548,12 +624,14 @@ HRESULT HostNetworkInterface::setVirtualBox(VirtualBox *pVBox)
if (m.IPAddress == 0 && mIfType == HostNetworkInterfaceType_HostOnly)
{
Bstr tmpAddr, tmpMask;
- HRESULT hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(), tmpAddr.asOutParam());
- hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(), tmpMask.asOutParam());
- if (tmpAddr.isEmpty())
+ HRESULT hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPAddress", mInterfaceName.raw()).raw(),
+ tmpAddr.asOutParam());
+ if (FAILED(hrc) || tmpAddr.isEmpty())
tmpAddr = getDefaultIPv4Address(mInterfaceName);
- if (tmpMask.isEmpty())
+ hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPNetMask", mInterfaceName.raw()).raw(),
+ tmpMask.asOutParam());
+ if (FAILED(hrc) || tmpMask.isEmpty())
tmpMask = Bstr(VBOXNET_IPV4MASK_DEFAULT);
m.IPAddress = inet_addr(Utf8Str(tmpAddr).c_str());
@@ -563,10 +641,12 @@ HRESULT HostNetworkInterface::setVirtualBox(VirtualBox *pVBox)
if (m.IPV6Address.isEmpty())
{
Bstr tmpPrefixLen;
- HRESULT hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(), m.IPV6Address.asOutParam());
- if (!m.IPV6Address.isEmpty())
+ HRESULT hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPV6Address", mInterfaceName.raw()).raw(),
+ m.IPV6Address.asOutParam());
+ if (SUCCEEDED(hrc) && !m.IPV6Address.isEmpty())
{
- hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPV6PrefixLen", mInterfaceName.raw()).raw(), tmpPrefixLen.asOutParam());
+ hrc = mVBox->GetExtraData(BstrFmt("HostOnly/%ls/IPV6PrefixLen", mInterfaceName.raw()).raw(),
+ tmpPrefixLen.asOutParam());
if (SUCCEEDED(hrc) && !tmpPrefixLen.isEmpty())
m.IPV6NetworkMaskPrefixLength = Utf8Str(tmpPrefixLen).toUInt32();
else
diff --git a/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp b/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp
index 9c6fe5c75..582d62354 100644
--- a/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp
+++ b/src/VBox/Main/src-server/HostUSBDeviceImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -32,7 +32,7 @@
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
-DEFINE_EMPTY_CTOR_DTOR (HostUSBDevice)
+DEFINE_EMPTY_CTOR_DTOR(HostUSBDevice)
HRESULT HostUSBDevice::FinalConstruct()
{
@@ -113,7 +113,7 @@ void HostUSBDevice::uninit()
if (mUsb != NULL)
{
- USBProxyService::freeDevice (mUsb);
+ USBProxyService::freeDevice(mUsb);
mUsb = NULL;
}
@@ -188,7 +188,7 @@ STDMETHODIMP HostUSBDevice::COMGETTER(Manufacturer)(BSTR *aManufacturer)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- Bstr (mUsb->pszManufacturer).cloneTo(aManufacturer);
+ Bstr(mUsb->pszManufacturer).cloneTo(aManufacturer);
return S_OK;
}
@@ -202,7 +202,7 @@ STDMETHODIMP HostUSBDevice::COMGETTER(Product)(BSTR *aProduct)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- Bstr (mUsb->pszProduct).cloneTo(aProduct);
+ Bstr(mUsb->pszProduct).cloneTo(aProduct);
return S_OK;
}
@@ -216,7 +216,7 @@ STDMETHODIMP HostUSBDevice::COMGETTER(SerialNumber)(BSTR *aSerialNumber)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- Bstr (mUsb->pszSerialNumber).cloneTo(aSerialNumber);
+ Bstr(mUsb->pszSerialNumber).cloneTo(aSerialNumber);
return S_OK;
}
@@ -230,7 +230,7 @@ STDMETHODIMP HostUSBDevice::COMGETTER(Address)(BSTR *aAddress)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- Bstr (mUsb->pszAddress).cloneTo(aAddress);
+ Bstr(mUsb->pszAddress).cloneTo(aAddress);
return S_OK;
}
@@ -304,7 +304,7 @@ STDMETHODIMP HostUSBDevice::COMGETTER(Remote)(BOOL *aRemote)
// IHostUSBDevice properties
/////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP HostUSBDevice::COMGETTER(State) (USBDeviceState_T *aState)
+STDMETHODIMP HostUSBDevice::COMGETTER(State)(USBDeviceState_T *aState)
{
CheckComArgOutPointerValid(aState);
@@ -330,18 +330,18 @@ Utf8Str HostUSBDevice::getName()
Utf8Str name;
AutoCaller autoCaller(this);
- AssertComRCReturn (autoCaller.rc(), name);
+ AssertComRCReturn(autoCaller.rc(), name);
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
bool haveManufacturer = mUsb->pszManufacturer && *mUsb->pszManufacturer;
bool haveProduct = mUsb->pszProduct && *mUsb->pszProduct;
if (haveManufacturer && haveProduct)
- name = Utf8StrFmt ("%s %s", mUsb->pszManufacturer, mUsb->pszProduct);
+ name = Utf8StrFmt("%s %s", mUsb->pszManufacturer, mUsb->pszProduct);
else if (haveManufacturer)
- name = Utf8StrFmt ("%s", mUsb->pszManufacturer);
+ name = Utf8StrFmt("%s", mUsb->pszManufacturer);
else if (haveProduct)
- name = Utf8StrFmt ("%s", mUsb->pszProduct);
+ name = Utf8StrFmt("%s", mUsb->pszProduct);
else
name = "<unknown>";
@@ -354,7 +354,7 @@ Utf8Str HostUSBDevice::getName()
*
* As a convenience, this method will operate like attachToVM() if the device
* is already held by the proxy. Note that it will then perform IPC to the VM
- * process, which means it will temporarily leave all locks. (Is this a good idea?)
+ * process, which means it will temporarily release all locks. (Is this a good idea?)
*
* @param aMachine Machine this device should be attach to.
* @param aSetError Whether to set full error message or not to bother.
@@ -364,19 +364,19 @@ Utf8Str HostUSBDevice::getName()
* @retval S_OK on success.
* @retval E_UNEXPECTED if the device state doesn't permit for any attaching.
* @retval E_* as appropriate.
- *
- * @note Must be called from under the object write lock.
- * @note May lock the given machine object for reading.
*/
HRESULT HostUSBDevice::requestCaptureForVM(SessionMachine *aMachine, bool aSetError, ULONG aMaskedIfs /* = 0*/)
{
- LogFlowThisFunc(("{%s} aMachine=%p aMaskedIfs=%#x\n", mName, aMachine, aMaskedIfs));
-
/*
* Validate preconditions and input.
*/
AssertReturn(aMachine, E_INVALIDARG);
- AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
+ AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
+ AssertReturn(!aMachine->isWriteLockOnCurrentThread(), E_FAIL);
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("{%s} aMachine=%p aMaskedIfs=%#x\n", mName, aMachine, aMaskedIfs));
+
if (aSetError)
{
if (mUniState == kHostUSBDeviceState_Unsupported)
@@ -390,6 +390,7 @@ HRESULT HostUSBDevice::requestCaptureForVM(SessionMachine *aMachine, bool aSetEr
if (mUniState == kHostUSBDeviceState_UsedByVM)
{
/* Machine::name() requires a read lock */
+ alock.release();
AutoReadLock machLock(mMachine COMMA_LOCKVAL_SRC_POS);
return setError(E_INVALIDARG,
tr("USB device '%s' with UUID {%RTuuid} is already captured by the virtual machine '%s'"),
@@ -419,6 +420,7 @@ HRESULT HostUSBDevice::requestCaptureForVM(SessionMachine *aMachine, bool aSetEr
*/
if (mUniState == kHostUSBDeviceState_HeldByProxy)
{
+ alock.release();
HRESULT hrc = attachToVM(aMachine, aMaskedIfs);
return SUCCEEDED(hrc);
}
@@ -438,9 +440,11 @@ HRESULT HostUSBDevice::requestCaptureForVM(SessionMachine *aMachine, bool aSetEr
#endif
mMachine = aMachine;
mMaskedIfs = aMaskedIfs;
+ alock.release();
int rc = mUSBProxyService->captureDevice(this);
if (RT_FAILURE(rc))
{
+ alock.acquire();
failTransition();
mMachine.setNull();
if (rc == VERR_SHARING_VIOLATION)
@@ -472,6 +476,8 @@ HRESULT HostUSBDevice::requestCaptureForVM(SessionMachine *aMachine, bool aSetEr
*/
HRESULT HostUSBDevice::attachToVM(SessionMachine *aMachine, ULONG aMaskedIfs /* = 0*/)
{
+ AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
/*
* Validate and update the state.
*/
@@ -482,15 +488,10 @@ HRESULT HostUSBDevice::attachToVM(SessionMachine *aMachine, ULONG aMaskedIfs /*
setState(kHostUSBDeviceState_AttachingToVM, kHostUSBDeviceState_UsedByVM);
/*
- * The VM process will query the object, so grab a reference to ourselves and leave the locks.
+ * The VM process will query the object, so grab a reference to ourselves and release the locks.
*/
ComPtr<IUSBDevice> d = this;
- AutoWriteLock alockSelf(this COMMA_LOCKVAL_SRC_POS);
- alockSelf.leave();
- AutoWriteLock alockProxy(mUSBProxyService COMMA_LOCKVAL_SRC_POS);
- alockProxy.leave();
-
/*
* Call the VM process (IPC) and request it to attach the device.
*
@@ -499,15 +500,15 @@ HRESULT HostUSBDevice::attachToVM(SessionMachine *aMachine, ULONG aMaskedIfs /*
* out of people.
*/
LogFlowThisFunc(("{%s} Calling machine->onUSBDeviceAttach()...\n", mName));
- HRESULT hrc = aMachine->onUSBDeviceAttach (d, NULL, aMaskedIfs);
+ alock.release();
+ HRESULT hrc = aMachine->onUSBDeviceAttach(d, NULL, aMaskedIfs);
LogFlowThisFunc(("{%s} Done machine->onUSBDeviceAttach()=%08X\n", mName, hrc));
/*
- * As we re-enter the lock, we'll have to check if the device was
+ * As we re-acquire the lock, we'll have to check if the device was
* physically detached while we were busy.
*/
- alockProxy.enter();
- alockSelf.enter();
+ alock.acquire();
if (SUCCEEDED(hrc))
{
@@ -516,6 +517,7 @@ HRESULT HostUSBDevice::attachToVM(SessionMachine *aMachine, ULONG aMaskedIfs /*
setState(kHostUSBDeviceState_UsedByVM);
else
{
+ alock.release();
detachFromVM(kHostUSBDeviceState_PhysDetached);
hrc = E_UNEXPECTED;
}
@@ -531,6 +533,7 @@ HRESULT HostUSBDevice::attachToVM(SessionMachine *aMachine, ULONG aMaskedIfs /*
}
else
{
+ alock.release();
onPhysicalDetachedInternal();
hrc = E_UNEXPECTED;
}
@@ -555,20 +558,18 @@ void HostUSBDevice::detachFromVM(HostUSBDeviceState aFinalState)
* Assert preconditions.
*/
Assert(aFinalState == kHostUSBDeviceState_PhysDetached);
+ AssertReturnVoid(!isWriteLockOnCurrentThread());
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
Assert( mUniState == kHostUSBDeviceState_AttachingToVM
|| mUniState == kHostUSBDeviceState_UsedByVM);
Assert(!mMachine.isNull());
/*
- * Change the state and abandond the locks. The VM may query
+ * Change the state and abandon the locks. The VM may query
* data and we don't want to deadlock - the state protects us,
* so, it's not a bit issue here.
*/
setState(kHostUSBDeviceState_PhysDetachingFromVM, kHostUSBDeviceState_PhysDetached);
- AutoWriteLock alockSelf(this COMMA_LOCKVAL_SRC_POS);
- alockSelf.leave();
- AutoWriteLock alockProxy(mUSBProxyService COMMA_LOCKVAL_SRC_POS);
- alockProxy.leave();
/*
* Call the VM process (IPC) and request it to detach the device.
@@ -577,16 +578,16 @@ void HostUSBDevice::detachFromVM(HostUSBDeviceState aFinalState)
* assert the return code as it will crash the daemon and annoy the heck
* out of people.
*/
+ alock.release();
LogFlowThisFunc(("{%s} Calling machine->onUSBDeviceDetach()...\n", mName));
HRESULT hrc = mMachine->onUSBDeviceDetach(mId.toUtf16().raw(), NULL);
LogFlowThisFunc(("{%s} Done machine->onUSBDeviceDetach()=%Rhrc\n", mName, hrc));
NOREF(hrc);
/*
- * Re-enter the locks and complete the transition.
+ * Re-acquire the locks and complete the transition.
*/
- alockProxy.enter();
- alockSelf.enter();
+ alock.acquire();
advanceTransition();
}
@@ -671,17 +672,18 @@ HRESULT HostUSBDevice::onDetachFromVM(SessionMachine *aMachine, bool aDone, bool
* @retval E_UNEXPECTED on bad state.
* @retval E_* as appropriate.
*
- * @note Must be called from under the object write lock.
+ * @note Must be called without holding the object lock.
*/
HRESULT HostUSBDevice::requestReleaseToHost()
{
- LogFlowThisFunc(("{%s}\n", mName));
-
/*
* Validate preconditions.
*/
- AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
+ AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
Assert(mMachine.isNull());
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("{%s}\n", mName));
if ( mUniState == kHostUSBDeviceState_Unused
|| mUniState == kHostUSBDeviceState_Capturable)
return S_OK;
@@ -696,9 +698,11 @@ HRESULT HostUSBDevice::requestReleaseToHost()
#else
startTransition(kHostUSBDeviceState_ReleasingToHost, kHostUSBDeviceState_Unused);
#endif
+ alock.release();
int rc = mUSBProxyService->releaseDevice(this);
if (RT_FAILURE(rc))
{
+ alock.acquire();
failTransition();
return E_FAIL;
}
@@ -717,16 +721,16 @@ HRESULT HostUSBDevice::requestReleaseToHost()
* @retval E_UNEXPECTED on bad state.
* @retval E_* as appropriate.
*
- * @note Must be called from under the object write lock.
+ * @note Must be called without holding the object lock.
*/
HRESULT HostUSBDevice::requestHold()
{
- LogFlowThisFunc(("{%s}\n", mName));
-
/*
* Validate preconditions.
*/
- AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
+ AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("{%s}\n", mName));
AssertMsgReturn( mUniState == kHostUSBDeviceState_Unused
|| mUniState == kHostUSBDeviceState_Capturable
|| mUniState == kHostUSBDeviceState_HeldByProxy,
@@ -748,9 +752,11 @@ HRESULT HostUSBDevice::requestHold()
#else
startTransition(kHostUSBDeviceState_Capturing, kHostUSBDeviceState_HeldByProxy);
#endif
+ alock.release();
int rc = mUSBProxyService->captureDevice(this);
if (RT_FAILURE(rc))
{
+ alock.acquire();
failTransition();
return E_FAIL;
}
@@ -795,9 +801,9 @@ bool HostUSBDevice::wasActuallyDetached()
{
#ifndef RT_OS_WINDOWS /* check the implementation details here. */
uint64_t elapsedNanoseconds = RTTimeNanoTS() - mLastStateChangeTS;
- if (elapsedNanoseconds > UINT64_C (60000000000) ) /* 60 seconds */
+ if (elapsedNanoseconds > UINT64_C(60000000000)) /* 60 seconds */
{
- LogRel (("USB: Async operation timed out for device %s (state: %s)\n", mName, getStateName()));
+ LogRel(("USB: Async operation timed out for device %s (state: %s)\n", mName, getStateName()));
failTransition();
}
#endif
@@ -822,7 +828,7 @@ bool HostUSBDevice::wasActuallyDetached()
break;
default:
- AssertLogRelMsgFailed (("this=%p %s\n", this, getStateName()));
+ AssertLogRelMsgFailed(("this=%p %s\n", this, getStateName()));
break;
}
@@ -837,19 +843,21 @@ bool HostUSBDevice::wasActuallyDetached()
* handled when the transition advances forward.
*
* Otherwise the device will be detached from any VM currently using it - this
- * involves IPC and will temporarily abandond locks - and all the device data
+ * involves IPC and will temporarily abandon locks - and all the device data
* reset.
- *
- * @note Must be called from under the object write lock.
*/
void HostUSBDevice::onPhysicalDetached()
{
+ AssertReturnVoid(!isWriteLockOnCurrentThread());
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("{%s}\n", mName));
- AssertReturnVoid(isWriteLockOnCurrentThread());
mIsPhysicallyDetached = true;
if (mUniState < kHostUSBDeviceState_FirstTransitional)
+ {
+ alock.release();
onPhysicalDetachedInternal();
+ }
}
@@ -858,13 +866,12 @@ void HostUSBDevice::onPhysicalDetached()
* at a transition state change.
*
* See onPhysicalDetach() for details.
- *
- * @note Must be called from under the object write lock.
*/
void HostUSBDevice::onPhysicalDetachedInternal()
{
+ AssertReturnVoid(!isWriteLockOnCurrentThread());
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("{%s}\n", mName));
- AssertReturnVoid(isWriteLockOnCurrentThread());
Assert(mIsPhysicallyDetached);
/*
@@ -873,7 +880,11 @@ void HostUSBDevice::onPhysicalDetachedInternal()
if ( !mMachine.isNull()
&& ( mUniState == kHostUSBDeviceState_UsedByVM
|| mUniState == kHostUSBDeviceState_AttachingToVM))
+ {
+ alock.release();
detachFromVM(kHostUSBDeviceState_PhysDetached);
+ alock.acquire();
+ }
else
AssertMsg(mMachine.isNull(), ("%s\n", getStateName()));
@@ -1060,8 +1071,6 @@ int HostUSBDevice::compare(PCUSBDEVICE aDev1, PCUSBDEVICE aDev2, bool aIsAwaitin
*
* @returns Whether the Host object should be bothered with this state change.
*
- * @note Locks this object for writing.
- *
* @todo Just do everything here, that is, call filter runners and everything that
* works by state change. Using 3 return codes/parameters is just plain ugly.
*/
@@ -1073,12 +1082,11 @@ bool HostUSBDevice::updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMach
/*
* Locking.
*/
- AssertReturn(isWriteLockOnCurrentThread(), false);
+ AssertReturn(!isWriteLockOnCurrentThread(), false);
AutoCaller autoCaller(this);
AssertComRCReturn(autoCaller.rc(), false);
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
/*
* Replace the existing structure by the new one.
*/
@@ -1137,7 +1145,7 @@ bool HostUSBDevice::updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMach
#endif
aDev->pNext = mUsb->pNext;
aDev->pPrev = mUsb->pPrev;
- USBProxyService::freeDevice (mUsb);
+ USBProxyService::freeDevice(mUsb);
mUsb = aDev;
}
@@ -1370,7 +1378,11 @@ bool HostUSBDevice::updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMach
/* Take action if we're supposed to attach it to a VM. */
if (mUniState == kHostUSBDeviceState_AttachingToVM)
+ {
+ alock.release();
attachToVM(mMachine, mMaskedIfs);
+ alock.acquire();
+ }
break;
/* Can only mean that we've failed capturing it. */
@@ -1459,7 +1471,6 @@ bool HostUSBDevice::updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMach
}
return fIsImportant;
-
}
@@ -1473,19 +1484,17 @@ bool HostUSBDevice::updateState(PCUSBDEVICE aDev, bool *aRunFilters, SessionMach
* @param[out] aIgnoreMachine See HostUSBDevice::updateState()
*
* @returns See HostUSBDevice::updateState()
- *
- * @note Caller must write lock the object.
*/
bool HostUSBDevice::updateStateFake(PCUSBDEVICE aDev, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
+ Assert(!isWriteLockOnCurrentThread());
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
const HostUSBDeviceState enmState = mUniState;
switch (enmState)
{
case kHostUSBDeviceState_Capturing:
case kHostUSBDeviceState_ReleasingToHost:
{
- Assert(isWriteLockOnCurrentThread());
-
*aIgnoreMachine = mUniState == kHostUSBDeviceState_ReleasingToHost ? mMachine : NULL;
*aRunFilters = advanceTransition();
LogThisFunc(("{%s} %s\n", mName, getStateName()));
@@ -1506,11 +1515,15 @@ bool HostUSBDevice::updateStateFake(PCUSBDEVICE aDev, bool *aRunFilters, Session
/* Take action if we're supposed to attach it to a VM. */
if (mUniState == kHostUSBDeviceState_AttachingToVM)
+ {
+ alock.release();
attachToVM(mMachine, mMaskedIfs);
+ }
return true;
}
default:
+ alock.release();
return updateState(aDev, aRunFilters, aIgnoreMachine);
}
}
@@ -1806,8 +1819,8 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
Assert(aNewSubState == kHostUSBDeviceSubState_Default);
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -1834,13 +1847,13 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
case kHostUSBDeviceState_UsedByVM:
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -1863,13 +1876,13 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
case kHostUSBDeviceState_UsedByVM:
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -1892,8 +1905,8 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
case kHostUSBDeviceState_UsedByVM:
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
case kHostUSBDeviceState_ReleasingToHost:
@@ -1902,13 +1915,13 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
case kHostUSBDeviceState_Unused: /* Only this! */
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -1930,13 +1943,13 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
case kHostUSBDeviceState_Unused: /* Only this! */
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -1960,8 +1973,8 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
case kHostUSBDeviceState_AttachingToVM: // ??
case kHostUSBDeviceState_UsedByVM:
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -2012,8 +2025,8 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -2056,8 +2069,8 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -2085,8 +2098,8 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -2121,8 +2134,8 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
@@ -2138,13 +2151,13 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
Assert(aNewSubState == kHostUSBDeviceSubState_Default);
break;
default:
- AssertLogRelMsgFailedReturn (("this=%p %s -X-> %s\n", this, getStateName(),
- stateName(aNewState, aNewPendingState, aNewSubState)), false);
+ AssertLogRelMsgFailedReturn(("this=%p %s -X-> %s\n", this, getStateName(),
+ stateName(aNewState, aNewPendingState, aNewSubState)), false);
}
break;
default:
- AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), false);
+ AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
}
/*
@@ -2167,7 +2180,6 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
}
-
/**
* A convenience for entering a transitional state.
@@ -2179,9 +2191,10 @@ bool HostUSBDevice::setState(HostUSBDeviceState aNewState, HostUSBDeviceState aN
*
* @note The caller must own the write lock for this object.
*/
-bool HostUSBDevice::startTransition (HostUSBDeviceState aNewState, HostUSBDeviceState aFinalState,
- HostUSBDeviceSubState aNewSubState /*= kHostUSBDeviceSubState_Default*/)
+bool HostUSBDevice::startTransition(HostUSBDeviceState aNewState, HostUSBDeviceState aFinalState,
+ HostUSBDeviceSubState aNewSubState /*= kHostUSBDeviceSubState_Default*/)
{
+ AssertReturn(isWriteLockOnCurrentThread(), false);
/*
* A quick prevalidation thing. Not really necessary since setState
* verifies this too, but it's very easy here.
@@ -2201,14 +2214,14 @@ bool HostUSBDevice::startTransition (HostUSBDeviceState aNewState, HostUSBDevice
case kHostUSBDeviceState_ReleasingToHost:
case kHostUSBDeviceState_AttachingToVM:
case kHostUSBDeviceState_PhysDetachingFromVM:
- AssertMsgFailedReturn (("this=%p %s is a transitional state.\n", this, getStateName()), false);
+ AssertMsgFailedReturn(("this=%p %s is a transitional state.\n", this, getStateName()), false);
case kHostUSBDeviceState_PhysDetached:
default:
- AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), false);
+ AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
}
- return setState (aNewState, aFinalState, aNewSubState);
+ return setState(aNewState, aFinalState, aNewSubState);
}
@@ -2224,6 +2237,7 @@ bool HostUSBDevice::startTransition (HostUSBDeviceState aNewState, HostUSBDevice
*/
bool HostUSBDevice::advanceTransition(bool aSkipReAttach /* = false */)
{
+ AssertReturn(isWriteLockOnCurrentThread(), false);
HostUSBDeviceState enmPending = mPendingUniState;
HostUSBDeviceSubState enmSub = mUniSubState;
HostUSBDeviceState enmState = mUniState;
@@ -2385,6 +2399,7 @@ bool HostUSBDevice::advanceTransition(bool aSkipReAttach /* = false */)
*/
bool HostUSBDevice::failTransition()
{
+ AssertReturn(isWriteLockOnCurrentThread(), false);
HostUSBDeviceSubState enmSub = mUniSubState;
HostUSBDeviceState enmState = mUniState;
switch (enmState)
@@ -2411,12 +2426,12 @@ bool HostUSBDevice::failTransition()
enmState = kHostUSBDeviceState_PhysDetached;
break;
default:
- AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), false);
+ AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
}
break;
case kHostUSBDeviceState_PhysDetachingFromVM:
- AssertMsgFailedReturn (("this=%p %s shall not fail\n", this, getStateName()), false);
+ AssertMsgFailedReturn(("this=%p %s shall not fail\n", this, getStateName()), false);
case kHostUSBDeviceState_Unsupported:
case kHostUSBDeviceState_UsedByHost:
@@ -2424,10 +2439,10 @@ bool HostUSBDevice::failTransition()
case kHostUSBDeviceState_Unused:
case kHostUSBDeviceState_HeldByProxy:
case kHostUSBDeviceState_UsedByVM:
- AssertMsgFailedReturn (("this=%p %s is not transitional\n", this, getStateName()), false);
+ AssertMsgFailedReturn(("this=%p %s is not transitional\n", this, getStateName()), false);
case kHostUSBDeviceState_PhysDetached:
default:
- AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), false);
+ AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), false);
}
@@ -2501,7 +2516,7 @@ USBDeviceState_T HostUSBDevice::canonicalState() const
case kHostUSBDeviceState_PhysDetached:
default:
- AssertReleaseMsgFailedReturn (("this=%p mUniState=%d\n", this, mUniState), USBDeviceState_NotSupported);
+ AssertReleaseMsgFailedReturn(("this=%p mUniState=%d\n", this, mUniState), USBDeviceState_NotSupported);
}
/* won't ever get here. */
}
diff --git a/src/VBox/Main/src-server/Logging.cpp b/src/VBox/Main/src-server/Logging.cpp
deleted file mode 100644
index 9b6d1e37e..000000000
--- a/src/VBox/Main/src-server/Logging.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $Id: Logging.cpp $ */
-
-/** @file
- *
- * Logging in VBoxSVC.
- */
-
-/*
- * Copyright (C) 2011 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "Logging.h"
-
-#include <package-generated.h>
-
-#include <iprt/buildconfig.h>
-#include <iprt/err.h>
-#include <iprt/message.h>
-#include <iprt/path.h>
-#include <iprt/system.h>
-#include <iprt/process.h>
-#include <VBox/version.h>
-#include <VBox/log.h>
-
-
-static void vboxsvcHeaderFooter(PRTLOGGER pLoggerRelease, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog)
-{
- /* some introductory information */
- static RTTIMESPEC s_TimeSpec;
- char szTmp[256];
- if (enmPhase == RTLOGPHASE_BEGIN)
- RTTimeNow(&s_TimeSpec);
- RTTimeSpecToString(&s_TimeSpec, szTmp, sizeof(szTmp));
-
- switch (enmPhase)
- {
- case RTLOGPHASE_BEGIN:
- {
- pfnLog(pLoggerRelease,
- "VirtualBox (XP)COM Server %s r%u %s (%s %s) release log\n"
-#ifdef VBOX_BLEEDING_EDGE
- "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n"
-#endif
- "Log opened %s\n",
- VBOX_VERSION_STRING, RTBldCfgRevision(), VBOX_BUILD_TARGET,
- __DATE__, __TIME__, szTmp);
-
- int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- pfnLog(pLoggerRelease, "OS Product: %s\n", szTmp);
- vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- pfnLog(pLoggerRelease, "OS Release: %s\n", szTmp);
- vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- pfnLog(pLoggerRelease, "OS Version: %s\n", szTmp);
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- pfnLog(pLoggerRelease, "OS Service Pack: %s\n", szTmp);
-
- /* the package type is interesting for Linux distributions */
- char szExecName[RTPATH_MAX];
- char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
- pfnLog(pLoggerRelease,
- "Executable: %s\n"
- "Process ID: %u\n"
- "Package type: %s"
-#ifdef VBOX_OSE
- " (OSE)"
-#endif
- "\n",
- pszExecName ? pszExecName : "unknown",
- RTProcSelf(),
- VBOX_PACKAGE_STRING);
- break;
- }
-
- case RTLOGPHASE_PREROTATE:
- pfnLog(pLoggerRelease, "Log rotated - Log started %s\n", szTmp);
- break;
-
- case RTLOGPHASE_POSTROTATE:
- pfnLog(pLoggerRelease, "Log continuation - Log started %s\n", szTmp);
- break;
-
- case RTLOGPHASE_END:
- pfnLog(pLoggerRelease, "End of log file - Log started %s\n", szTmp);
- break;
-
- default:
- /* nothing */;
- }
-}
-
-int VBoxSVCLogRelCreate(const char *pszLogFile, uint32_t cHistory,
- uint32_t uHistoryFileTime, uint64_t uHistoryFileSize)
-{
- /* create release logger */
- PRTLOGGER pLoggerReleaseFile;
- static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
- RTUINT fFlags = RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG;
-#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
- fFlags |= RTLOGFLAGS_USECRLF;
-#endif
- char szError[RTPATH_MAX + 128] = "";
- int vrc = RTLogCreateEx(&pLoggerReleaseFile, fFlags, "all",
- "VBOXSVC_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, 0 /* fDestFlags */,
- vboxsvcHeaderFooter, cHistory, uHistoryFileSize, uHistoryFileTime,
- szError, sizeof(szError), pszLogFile);
- if (RT_SUCCESS(vrc))
- {
- /* register this logger as the release logger */
- RTLogRelSetDefaultInstance(pLoggerReleaseFile);
-
- /* Explicitly flush the log in case of VBOXWEBSRV_RELEASE_LOG=buffered. */
- RTLogFlush(pLoggerReleaseFile);
- }
- else
- {
- /* print a message, but do not fail */
- RTMsgError("failed to open release log (%s, %Rrc)", szError, vrc);
- }
- return vrc;
-}
-
-/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index 78afdd7bf..100f696e6 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2004-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -50,6 +50,7 @@
#include "DisplayUtils.h"
#include "BandwidthControlImpl.h"
#include "MachineImplCloneVM.h"
+#include "AutostartDb.h"
// generated header
#include "VBoxEvents.h"
@@ -59,6 +60,7 @@
#endif
#include "AutoCaller.h"
+#include "HashedPw.h"
#include "Performance.h"
#include <iprt/asm.h>
@@ -69,6 +71,7 @@
#include <iprt/process.h>
#include <iprt/cpp/utils.h>
#include <iprt/cpp/xml.h> /* xml::XmlFileWriter::s_psz*Suff. */
+#include <iprt/sha.h>
#include <iprt/string.h>
#include <VBox/com/array.h>
@@ -88,8 +91,6 @@
#include <algorithm>
-#include <typeinfo>
-
#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
# define HOSTSUFF_EXE ".exe"
#else /* !RT_OS_WINDOWS */
@@ -129,7 +130,7 @@ Machine::Data::Data()
mCurrentStateModified = TRUE;
mGuestPropertiesModified = FALSE;
- mSession.mPid = NIL_RTPROCESS;
+ mSession.mPID = NIL_RTPROCESS;
mSession.mState = SessionState_Unlocked;
}
@@ -164,6 +165,11 @@ Machine::HWData::HWData()
mAccelerate3DEnabled = false;
mAccelerate2DVideoEnabled = false;
mMonitorCount = 1;
+ mVideoCaptureFile = "Test.webm";
+ mVideoCaptureWidth = 640;
+ mVideoCaptureHeight = 480;
+ mVideoCaptureEnabled = false;
+
mHWVirtExEnabled = true;
mHWVirtExNestedPagingEnabled = true;
#if HC_ARCH_BITS == 64 && !defined(RT_OS_LINUX)
@@ -185,7 +191,7 @@ Machine::HWData::HWData()
mPAEEnabled = false;
#endif
mSyntheticCpu = false;
- mHpetEnabled = false;
+ mHPETEnabled = false;
/* default boot order: floppy - DVD - HDD */
mBootOrder[0] = DeviceType_Floppy;
@@ -194,20 +200,21 @@ Machine::HWData::HWData()
for (size_t i = 3; i < RT_ELEMENTS(mBootOrder); ++i)
mBootOrder[i] = DeviceType_Null;
- mClipboardMode = ClipboardMode_Bidirectional;
+ mClipboardMode = ClipboardMode_Disabled;
+ mDragAndDropMode = DragAndDropMode_Disabled;
mGuestPropertyNotificationPatterns = "";
mFirmwareType = FirmwareType_BIOS;
- mKeyboardHidType = KeyboardHidType_PS2Keyboard;
- mPointingHidType = PointingHidType_PS2Mouse;
+ mKeyboardHIDType = KeyboardHIDType_PS2Keyboard;
+ mPointingHIDType = PointingHIDType_PS2Mouse;
mChipsetType = ChipsetType_PIIX3;
mEmulatedUSBCardReaderEnabled = FALSE;
for (size_t i = 0; i < RT_ELEMENTS(mCPUAttached); i++)
mCPUAttached[i] = false;
- mIoCacheEnabled = true;
- mIoCacheSize = 5; /* 5MB */
+ mIOCacheEnabled = true;
+ mIOCacheSize = 5; /* 5MB */
/* Maximum CPU execution cap by default. */
mCpuExecutionCap = 100;
@@ -239,7 +246,10 @@ Machine::MediaData::~MediaData()
Machine::Machine()
: mCollectorGuest(NULL),
mPeer(NULL),
- mParent(NULL)
+ mParent(NULL),
+ mSerialPorts(),
+ mParallelPorts(),
+ uRegistryNeedsSaving(0)
{}
Machine::~Machine()
@@ -266,8 +276,9 @@ void Machine::FinalRelease()
* @param strConfigFile Local file system path to the VM settings file (can
* be relative to the VirtualBox config directory).
* @param strName name for the machine
- * @param aId UUID for the new machine.
+ * @param llGroups list of groups for the machine
* @param aOsType OS Type of this machine or NULL.
+ * @param aId UUID for the new machine.
* @param fForceOverwrite Whether to overwrite an existing machine settings file.
*
* @return Success indicator. if not S_OK, the machine object is invalid
@@ -275,9 +286,11 @@ void Machine::FinalRelease()
HRESULT Machine::init(VirtualBox *aParent,
const Utf8Str &strConfigFile,
const Utf8Str &strName,
+ const StringsList &llGroups,
GuestOSType *aOsType,
const Guid &aId,
- bool fForceOverwrite)
+ bool fForceOverwrite,
+ bool fDirectoryIncludesUUID)
{
LogFlowThisFuncEnter();
LogFlowThisFunc(("(Init_New) aConfigFile='%s'\n", strConfigFile.c_str()));
@@ -309,6 +322,9 @@ HRESULT Machine::init(VirtualBox *aParent,
mUserData->s.strName = strName;
+ mUserData->s.llGroups = llGroups;
+
+ mUserData->s.fDirectoryIncludesUUID = fDirectoryIncludesUUID;
// the "name sync" flag determines whether the machine directory gets renamed along
// with the machine file; say so if the settings file name is the same as the
// settings file parent directory (machine directory)
@@ -327,7 +343,7 @@ HRESULT Machine::init(VirtualBox *aParent,
mBIOSSettings->applyDefaults(aOsType);
/* Apply network adapters defaults */
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); ++slot)
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); ++slot)
mNetworkAdapters[slot]->applyDefaults(aOsType);
/* Apply serial port defaults */
@@ -380,9 +396,9 @@ HRESULT Machine::init(VirtualBox *aParent,
*
* @return Success indicator. if not S_OK, the machine object is invalid
*/
-HRESULT Machine::init(VirtualBox *aParent,
- const Utf8Str &strConfigFile,
- const Guid *aId)
+HRESULT Machine::initFromSettings(VirtualBox *aParent,
+ const Utf8Str &strConfigFile,
+ const Guid *aId)
{
LogFlowThisFuncEnter();
LogFlowThisFunc(("(Init_Registered) aConfigFile='%s\n", strConfigFile.c_str()));
@@ -450,7 +466,7 @@ HRESULT Machine::init(VirtualBox *aParent,
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
}
}
@@ -705,7 +721,7 @@ HRESULT Machine::registeredInit()
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
/* Restore the registered flag (even on failure) */
@@ -720,6 +736,8 @@ HRESULT Machine::registeredInit()
/* commit all changes made during loading the settings file */
commit(); // @todo r=dj why do we need a commit during init?!? this is very expensive
+ /// @todo r=klaus for some reason the settings loading logic backs up
+ // the settings, and therefore a commit is needed. Should probably be changed.
}
else
{
@@ -767,6 +785,17 @@ void Machine::uninit()
Assert(!isWriteLockOnCurrentThread());
+ Assert(!uRegistryNeedsSaving);
+ if (uRegistryNeedsSaving)
+ {
+ AutoCaller autoCaller(this);
+ if (SUCCEEDED(autoCaller.rc()))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ saveSettings(NULL, Machine::SaveS_Force);
+ }
+ }
+
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan(this);
if (autoUninitSpan.uninitDone())
@@ -817,6 +846,9 @@ void Machine::uninit()
// uninit media from this machine's media registry, if they're still there
Guid uuidMachine(getId());
+ /* the lock is no more necessary (SessionMachine is uninitialized) */
+ alock.release();
+
/* XXX This will fail with
* "cannot be closed because it is still attached to 1 virtual machines"
* because at this point we did not call uninitDataAndChildObjects() yet
@@ -824,9 +856,6 @@ void Machine::uninit()
if (!uuidMachine.isEmpty()) // can be empty if we're called from a failure of Machine::init
mParent->unregisterMachineMedia(uuidMachine);
- /* the lock is no more necessary (SessionMachine is uninitialized) */
- alock.leave();
-
// has machine been modified?
if (mData->flModifications)
{
@@ -1006,7 +1035,10 @@ STDMETHODIMP Machine::COMSETTER(Description)(IN_BSTR aDescription)
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- HRESULT rc = checkStateDependency(MutableStateDep);
+ // this can be done in principle in any state as it doesn't affect the VM
+ // significantly, but play safe by not messing around while complex
+ // activities are going on
+ HRESULT rc = checkStateDependency(MutableOrSavedStateDep);
if (FAILED(rc)) return rc;
setModified(IsModified_MachineData);
@@ -1030,6 +1062,51 @@ STDMETHODIMP Machine::COMGETTER(Id)(BSTR *aId)
return S_OK;
}
+STDMETHODIMP Machine::COMGETTER(Groups)(ComSafeArrayOut(BSTR, aGroups))
+{
+ CheckComArgOutSafeArrayPointerValid(aGroups);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ SafeArray<BSTR> groups(mUserData->s.llGroups.size());
+ size_t i = 0;
+ for (StringsList::const_iterator it = mUserData->s.llGroups.begin();
+ it != mUserData->s.llGroups.end();
+ ++it, i++)
+ {
+ Bstr tmp = *it;
+ tmp.cloneTo(&groups[i]);
+ }
+ groups.detachTo(ComSafeArrayOutArg(aGroups));
+
+ return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(Groups)(ComSafeArrayIn(IN_BSTR, aGroups))
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ StringsList llGroups;
+ HRESULT rc = mParent->convertMachineGroups(ComSafeArrayInArg(aGroups), &llGroups);
+ if (FAILED(rc))
+ return rc;
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ // changing machine groups is possible while the VM is offline
+ rc = checkStateDependency(OfflineStateDep);
+ if (FAILED(rc)) return rc;
+
+ setModified(IsModified_MachineData);
+ mUserData.backup();
+ mUserData->s.llGroups = llGroups;
+
+ return S_OK;
+}
+
STDMETHODIMP Machine::COMGETTER(OSTypeId)(BSTR *aOSTypeId)
{
CheckComArgOutPointerValid(aOSTypeId);
@@ -1095,7 +1172,7 @@ STDMETHODIMP Machine::COMSETTER(FirmwareType)(FirmwareType_T aFirmwareType)
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- int rc = checkStateDependency(MutableStateDep);
+ HRESULT rc = checkStateDependency(MutableStateDep);
if (FAILED(rc)) return rc;
setModified(IsModified_MachineData);
@@ -1105,62 +1182,62 @@ STDMETHODIMP Machine::COMSETTER(FirmwareType)(FirmwareType_T aFirmwareType)
return S_OK;
}
-STDMETHODIMP Machine::COMGETTER(KeyboardHidType)(KeyboardHidType_T *aKeyboardHidType)
+STDMETHODIMP Machine::COMGETTER(KeyboardHIDType)(KeyboardHIDType_T *aKeyboardHIDType)
{
- CheckComArgOutPointerValid(aKeyboardHidType);
+ CheckComArgOutPointerValid(aKeyboardHIDType);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aKeyboardHidType = mHWData->mKeyboardHidType;
+ *aKeyboardHIDType = mHWData->mKeyboardHIDType;
return S_OK;
}
-STDMETHODIMP Machine::COMSETTER(KeyboardHidType)(KeyboardHidType_T aKeyboardHidType)
+STDMETHODIMP Machine::COMSETTER(KeyboardHIDType)(KeyboardHIDType_T aKeyboardHIDType)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- int rc = checkStateDependency(MutableStateDep);
+ HRESULT rc = checkStateDependency(MutableStateDep);
if (FAILED(rc)) return rc;
setModified(IsModified_MachineData);
mHWData.backup();
- mHWData->mKeyboardHidType = aKeyboardHidType;
+ mHWData->mKeyboardHIDType = aKeyboardHIDType;
return S_OK;
}
-STDMETHODIMP Machine::COMGETTER(PointingHidType)(PointingHidType_T *aPointingHidType)
+STDMETHODIMP Machine::COMGETTER(PointingHIDType)(PointingHIDType_T *aPointingHIDType)
{
- CheckComArgOutPointerValid(aPointingHidType);
+ CheckComArgOutPointerValid(aPointingHIDType);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aPointingHidType = mHWData->mPointingHidType;
+ *aPointingHIDType = mHWData->mPointingHIDType;
return S_OK;
}
-STDMETHODIMP Machine::COMSETTER(PointingHidType)(PointingHidType_T aPointingHidType)
+STDMETHODIMP Machine::COMSETTER(PointingHIDType)(PointingHIDType_T aPointingHIDType)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- int rc = checkStateDependency(MutableStateDep);
+ HRESULT rc = checkStateDependency(MutableStateDep);
if (FAILED(rc)) return rc;
setModified(IsModified_MachineData);
mHWData.backup();
- mHWData->mPointingHidType = aPointingHidType;
+ mHWData->mPointingHIDType = aPointingHIDType;
return S_OK;
}
@@ -1185,20 +1262,37 @@ STDMETHODIMP Machine::COMSETTER(ChipsetType)(ChipsetType_T aChipsetType)
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- int rc = checkStateDependency(MutableStateDep);
+ HRESULT rc = checkStateDependency(MutableStateDep);
if (FAILED(rc)) return rc;
- setModified(IsModified_MachineData);
- mHWData.backup();
- mHWData->mChipsetType = aChipsetType;
+ if (aChipsetType != mHWData->mChipsetType)
+ {
+ setModified(IsModified_MachineData);
+ mHWData.backup();
+ mHWData->mChipsetType = aChipsetType;
+
+ // Resize network adapter array, to be finalized on commit/rollback.
+ // We must not throw away entries yet, otherwise settings are lost
+ // without a way to roll back.
+ uint32_t newCount = Global::getMaxNetworkAdapters(aChipsetType);
+ uint32_t oldCount = mNetworkAdapters.size();
+ if (newCount > oldCount)
+ {
+ mNetworkAdapters.resize(newCount);
+ for (ULONG slot = oldCount; slot < mNetworkAdapters.size(); slot++)
+ {
+ unconst(mNetworkAdapters[slot]).createObject();
+ mNetworkAdapters[slot]->init(this, slot);
+ }
+ }
+ }
return S_OK;
}
STDMETHODIMP Machine::COMGETTER(HardwareVersion)(BSTR *aHWVersion)
{
- if (!aHWVersion)
- return E_POINTER;
+ CheckComArgOutPointerValid(aHWVersion);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1277,8 +1371,7 @@ STDMETHODIMP Machine::COMSETTER(HardwareUUID)(IN_BSTR aUUID)
STDMETHODIMP Machine::COMGETTER(MemorySize)(ULONG *memorySize)
{
- if (!memorySize)
- return E_POINTER;
+ CheckComArgOutPointerValid(memorySize);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1317,8 +1410,7 @@ STDMETHODIMP Machine::COMSETTER(MemorySize)(ULONG memorySize)
STDMETHODIMP Machine::COMGETTER(CPUCount)(ULONG *CPUCount)
{
- if (!CPUCount)
- return E_POINTER;
+ CheckComArgOutPointerValid(CPUCount);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1370,8 +1462,7 @@ STDMETHODIMP Machine::COMSETTER(CPUCount)(ULONG CPUCount)
STDMETHODIMP Machine::COMGETTER(CPUExecutionCap)(ULONG *aExecutionCap)
{
- if (!aExecutionCap)
- return E_POINTER;
+ CheckComArgOutPointerValid(aExecutionCap);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1419,8 +1510,7 @@ STDMETHODIMP Machine::COMSETTER(CPUExecutionCap)(ULONG aExecutionCap)
STDMETHODIMP Machine::COMGETTER(CPUHotPlugEnabled)(BOOL *enabled)
{
- if (!enabled)
- return E_POINTER;
+ CheckComArgOutPointerValid(enabled);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1516,7 +1606,7 @@ STDMETHODIMP Machine::COMSETTER(EmulatedUSBCardReaderEnabled)(BOOL enabled)
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- int rc = checkStateDependency(MutableStateDep);
+ HRESULT rc = checkStateDependency(MutableStateDep);
if (FAILED(rc)) return rc;
setModified(IsModified_MachineData);
@@ -1542,7 +1632,7 @@ STDMETHODIMP Machine::COMSETTER(EmulatedUSBWebcameraEnabled)(BOOL enabled)
return E_NOTIMPL;
}
-STDMETHODIMP Machine::COMGETTER(HpetEnabled)(BOOL *enabled)
+STDMETHODIMP Machine::COMGETTER(HPETEnabled)(BOOL *enabled)
{
CheckComArgOutPointerValid(enabled);
@@ -1550,12 +1640,12 @@ STDMETHODIMP Machine::COMGETTER(HpetEnabled)(BOOL *enabled)
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *enabled = mHWData->mHpetEnabled;
+ *enabled = mHWData->mHPETEnabled;
return S_OK;
}
-STDMETHODIMP Machine::COMSETTER(HpetEnabled)(BOOL enabled)
+STDMETHODIMP Machine::COMSETTER(HPETEnabled)(BOOL enabled)
{
HRESULT rc = S_OK;
@@ -1569,15 +1659,103 @@ STDMETHODIMP Machine::COMSETTER(HpetEnabled)(BOOL enabled)
setModified(IsModified_MachineData);
mHWData.backup();
- mHWData->mHpetEnabled = enabled;
+ mHWData->mHPETEnabled = enabled;
return rc;
}
+STDMETHODIMP Machine::COMGETTER(VideoCaptureEnabled)(BOOL *fEnabled)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *fEnabled = mHWData->mVideoCaptureEnabled;
+ return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(VideoCaptureEnabled)(BOOL fEnabled)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ mHWData->mVideoCaptureEnabled = fEnabled;
+ return S_OK;
+}
+
+STDMETHODIMP Machine::COMGETTER(VideoCaptureFile)(BSTR * apFile)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ mHWData->mVideoCaptureFile.cloneTo(apFile);
+ return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(VideoCaptureFile)(IN_BSTR aFile)
+{
+ Utf8Str strFile(aFile);
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (strFile.isEmpty())
+ strFile = "VideoCap.webm";
+ mHWData->mVideoCaptureFile = strFile;
+ return S_OK;
+}
+
+
+STDMETHODIMP Machine::COMGETTER(VideoCaptureWidth)(ULONG *ulHorzRes)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ *ulHorzRes = mHWData->mVideoCaptureWidth;
+ return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(VideoCaptureWidth)(ULONG ulHorzRes)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc()))
+ {
+ LogFlow(("Autolocked failed\n"));
+ return autoCaller.rc();
+ }
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ mHWData->mVideoCaptureWidth = ulHorzRes;
+ return S_OK;
+}
+
+STDMETHODIMP Machine::COMGETTER(VideoCaptureHeight)(ULONG *ulVertRes)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ *ulVertRes = mHWData->mVideoCaptureHeight;
+ return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(VideoCaptureHeight)(ULONG ulVertRes)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ mHWData->mVideoCaptureHeight = ulVertRes;
+ return S_OK;
+}
+
STDMETHODIMP Machine::COMGETTER(VRAMSize)(ULONG *memorySize)
{
- if (!memorySize)
- return E_POINTER;
+ CheckComArgOutPointerValid(memorySize);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1616,8 +1794,7 @@ STDMETHODIMP Machine::COMSETTER(VRAMSize)(ULONG memorySize)
/** @todo this method should not be public */
STDMETHODIMP Machine::COMGETTER(MemoryBalloonSize)(ULONG *memoryBalloonSize)
{
- if (!memoryBalloonSize)
- return E_POINTER;
+ CheckComArgOutPointerValid(memoryBalloonSize);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1663,8 +1840,7 @@ STDMETHODIMP Machine::COMSETTER(MemoryBalloonSize)(ULONG memoryBalloonSize)
STDMETHODIMP Machine::COMGETTER(PageFusionEnabled) (BOOL *enabled)
{
- if (!enabled)
- return E_POINTER;
+ CheckComArgOutPointerValid(enabled);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1696,8 +1872,7 @@ STDMETHODIMP Machine::COMSETTER(PageFusionEnabled) (BOOL enabled)
STDMETHODIMP Machine::COMGETTER(Accelerate3DEnabled)(BOOL *enabled)
{
- if (!enabled)
- return E_POINTER;
+ CheckComArgOutPointerValid(enabled);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1731,8 +1906,7 @@ STDMETHODIMP Machine::COMSETTER(Accelerate3DEnabled)(BOOL enable)
STDMETHODIMP Machine::COMGETTER(Accelerate2DVideoEnabled)(BOOL *enabled)
{
- if (!enabled)
- return E_POINTER;
+ CheckComArgOutPointerValid(enabled);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1765,8 +1939,7 @@ STDMETHODIMP Machine::COMSETTER(Accelerate2DVideoEnabled)(BOOL enable)
STDMETHODIMP Machine::COMGETTER(MonitorCount)(ULONG *monitorCount)
{
- if (!monitorCount)
- return E_POINTER;
+ CheckComArgOutPointerValid(monitorCount);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1803,8 +1976,7 @@ STDMETHODIMP Machine::COMSETTER(MonitorCount)(ULONG monitorCount)
STDMETHODIMP Machine::COMGETTER(BIOSSettings)(IBIOSSettings **biosSettings)
{
- if (!biosSettings)
- return E_POINTER;
+ CheckComArgOutPointerValid(biosSettings);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1817,8 +1989,7 @@ STDMETHODIMP Machine::COMGETTER(BIOSSettings)(IBIOSSettings **biosSettings)
STDMETHODIMP Machine::GetCPUProperty(CPUPropertyType_T property, BOOL *aVal)
{
- if (!aVal)
- return E_POINTER;
+ CheckComArgOutPointerValid(aVal);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2075,8 +2246,7 @@ STDMETHODIMP Machine::RemoveAllCPUIDLeaves()
STDMETHODIMP Machine::GetHWVirtExProperty(HWVirtExPropertyType_T property, BOOL *aVal)
{
- if (!aVal)
- return E_POINTER;
+ CheckComArgOutPointerValid(aVal);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2233,8 +2403,7 @@ STDMETHODIMP Machine::COMSETTER(SnapshotFolder)(IN_BSTR aSnapshotFolder)
STDMETHODIMP Machine::COMGETTER(MediumAttachments)(ComSafeArrayOut(IMediumAttachment*, aAttachments))
{
- if (ComSafeArrayOutIsNull(aAttachments))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aAttachments);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2249,8 +2418,7 @@ STDMETHODIMP Machine::COMGETTER(MediumAttachments)(ComSafeArrayOut(IMediumAttach
STDMETHODIMP Machine::COMGETTER(VRDEServer)(IVRDEServer **vrdeServer)
{
- if (!vrdeServer)
- return E_POINTER;
+ CheckComArgOutPointerValid(vrdeServer);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2265,8 +2433,7 @@ STDMETHODIMP Machine::COMGETTER(VRDEServer)(IVRDEServer **vrdeServer)
STDMETHODIMP Machine::COMGETTER(AudioAdapter)(IAudioAdapter **audioAdapter)
{
- if (!audioAdapter)
- return E_POINTER;
+ CheckComArgOutPointerValid(audioAdapter);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2367,24 +2534,23 @@ STDMETHODIMP Machine::COMGETTER(SessionType)(BSTR *aSessionType)
return S_OK;
}
-STDMETHODIMP Machine::COMGETTER(SessionPid)(ULONG *aSessionPid)
+STDMETHODIMP Machine::COMGETTER(SessionPID)(ULONG *aSessionPID)
{
- CheckComArgOutPointerValid(aSessionPid);
+ CheckComArgOutPointerValid(aSessionPID);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aSessionPid = mData->mSession.mPid;
+ *aSessionPID = mData->mSession.mPID;
return S_OK;
}
STDMETHODIMP Machine::COMGETTER(State)(MachineState_T *machineState)
{
- if (!machineState)
- return E_POINTER;
+ CheckComArgOutPointerValid(machineState);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2522,18 +2688,66 @@ STDMETHODIMP Machine::COMGETTER(ClipboardMode)(ClipboardMode_T *aClipboardMode)
STDMETHODIMP
Machine::COMSETTER(ClipboardMode)(ClipboardMode_T aClipboardMode)
{
+ HRESULT rc = S_OK;
+
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- HRESULT rc = checkStateDependency(MutableStateDep);
+ alock.release();
+ rc = onClipboardModeChange(aClipboardMode);
+ alock.acquire();
if (FAILED(rc)) return rc;
setModified(IsModified_MachineData);
mHWData.backup();
mHWData->mClipboardMode = aClipboardMode;
+ /* Save settings if online - todo why is this required?? */
+ if (Global::IsOnline(mData->mMachineState))
+ saveSettings(NULL);
+
+ return S_OK;
+}
+
+STDMETHODIMP Machine::COMGETTER(DragAndDropMode)(DragAndDropMode_T *aDragAndDropMode)
+{
+ CheckComArgOutPointerValid(aDragAndDropMode);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aDragAndDropMode = mHWData->mDragAndDropMode;
+
+ return S_OK;
+}
+
+STDMETHODIMP
+Machine::COMSETTER(DragAndDropMode)(DragAndDropMode_T aDragAndDropMode)
+{
+ HRESULT rc = S_OK;
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ alock.release();
+ rc = onDragAndDropModeChange(aDragAndDropMode);
+ alock.acquire();
+ if (FAILED(rc)) return rc;
+
+ setModified(IsModified_MachineData);
+ mHWData.backup();
+ mHWData->mDragAndDropMode = aDragAndDropMode;
+
+ /* Save settings if online - todo why is this required?? */
+ if (Global::IsOnline(mData->mMachineState))
+ saveSettings(NULL);
+
return S_OK;
}
@@ -2553,7 +2767,7 @@ Machine::COMGETTER(GuestPropertyNotificationPatterns)(BSTR *aPatterns)
}
catch (...)
{
- return VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ return VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
return S_OK;
@@ -2706,30 +2920,47 @@ STDMETHODIMP Machine::COMGETTER(TeleporterPassword)(BSTR *aPassword)
CheckComArgOutPointerValid(aPassword);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- mUserData->s.strTeleporterPassword.cloneTo(aPassword);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ mUserData->s.strTeleporterPassword.cloneTo(aPassword);
+ }
- return S_OK;
+ return hrc;
}
STDMETHODIMP Machine::COMSETTER(TeleporterPassword)(IN_BSTR aPassword)
{
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = checkStateDependency(MutableStateDep);
- if (FAILED(rc)) return rc;
+ /*
+ * Hash the password first.
+ */
+ Utf8Str strPassword(aPassword);
+ if (!strPassword.isEmpty())
+ {
+ if (VBoxIsPasswordHashed(&strPassword))
+ return setError(E_INVALIDARG, tr("Cannot set an already hashed password, only plain text password please"));
+ VBoxHashPassword(&strPassword);
+ }
- setModified(IsModified_MachineData);
- mUserData.backup();
- mUserData->s.strTeleporterPassword = aPassword;
+ /*
+ * Do the update.
+ */
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = checkStateDependency(MutableStateDep);
+ if (SUCCEEDED(hrc))
+ {
+ setModified(IsModified_MachineData);
+ mUserData.backup();
+ mUserData->s.strTeleporterPassword = strPassword;
+ }
+ }
- return S_OK;
+ return hrc;
}
STDMETHODIMP Machine::COMGETTER(FaultToleranceState)(FaultToleranceState_T *aState)
@@ -2927,7 +3158,7 @@ STDMETHODIMP Machine::COMSETTER(RTCUseUTC)(BOOL aEnabled)
return S_OK;
}
-STDMETHODIMP Machine::COMGETTER(IoCacheEnabled)(BOOL *aEnabled)
+STDMETHODIMP Machine::COMGETTER(IOCacheEnabled)(BOOL *aEnabled)
{
CheckComArgOutPointerValid(aEnabled);
@@ -2936,12 +3167,12 @@ STDMETHODIMP Machine::COMGETTER(IoCacheEnabled)(BOOL *aEnabled)
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aEnabled = mHWData->mIoCacheEnabled;
+ *aEnabled = mHWData->mIOCacheEnabled;
return S_OK;
}
-STDMETHODIMP Machine::COMSETTER(IoCacheEnabled)(BOOL aEnabled)
+STDMETHODIMP Machine::COMSETTER(IOCacheEnabled)(BOOL aEnabled)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2953,26 +3184,26 @@ STDMETHODIMP Machine::COMSETTER(IoCacheEnabled)(BOOL aEnabled)
setModified(IsModified_MachineData);
mHWData.backup();
- mHWData->mIoCacheEnabled = aEnabled;
+ mHWData->mIOCacheEnabled = aEnabled;
return S_OK;
}
-STDMETHODIMP Machine::COMGETTER(IoCacheSize)(ULONG *aIoCacheSize)
+STDMETHODIMP Machine::COMGETTER(IOCacheSize)(ULONG *aIOCacheSize)
{
- CheckComArgOutPointerValid(aIoCacheSize);
+ CheckComArgOutPointerValid(aIOCacheSize);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aIoCacheSize = mHWData->mIoCacheSize;
+ *aIOCacheSize = mHWData->mIOCacheSize;
return S_OK;
}
-STDMETHODIMP Machine::COMSETTER(IoCacheSize)(ULONG aIoCacheSize)
+STDMETHODIMP Machine::COMSETTER(IOCacheSize)(ULONG aIOCacheSize)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -2984,7 +3215,7 @@ STDMETHODIMP Machine::COMSETTER(IoCacheSize)(ULONG aIoCacheSize)
setModified(IsModified_MachineData);
mHWData.backup();
- mHWData->mIoCacheSize = aIoCacheSize;
+ mHWData->mIOCacheSize = aIOCacheSize;
return S_OK;
}
@@ -3055,12 +3286,12 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
AssertReturn(!pSessionMachine.isNull(), E_FAIL);
/*
- * Leave the lock before calling the client process. It's safe here
+ * Release the lock before calling the client process. It's safe here
* since the only thing to do after we get the lock again is to add
* the remote control to the list (which doesn't directly influence
* anything).
*/
- alock.leave();
+ alock.release();
// get the console of the session holding the write lock (this is a remote call)
ComPtr<IConsole> pConsoleW;
@@ -3083,9 +3314,9 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
// the failure may occur w/o any error info (from RPC), so provide one
return setError(VBOX_E_VM_ERROR,
tr("Failed to assign the machine to the session (%Rrc)"), rc);
- alock.enter();
+ alock.acquire();
- // need to revalidate the state after entering the lock again
+ // need to revalidate the state after acquiring the lock again
if (mData->mSession.mState != SessionState_Locked)
{
pSessionControl->Uninitialize();
@@ -3127,14 +3358,14 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
// then the calling process must be the one that got started by
// LaunchVMProcess()
- LogFlowThisFunc(("mSession.mPid=%d(0x%x)\n", mData->mSession.mPid, mData->mSession.mPid));
+ LogFlowThisFunc(("mSession.mPID=%d(0x%x)\n", mData->mSession.mPID, mData->mSession.mPID));
LogFlowThisFunc(("session.pid=%d(0x%x)\n", pid, pid));
- if (mData->mSession.mPid != pid)
+ if (mData->mSession.mPID != pid)
return setError(E_ACCESSDENIED,
tr("An unexpected process (PID=0x%08X) has tried to lock the "
"machine '%s', while only the process started by LaunchVMProcess (PID=0x%08X) is allowed"),
- pid, mUserData->s.strName.c_str(), mData->mSession.mPid);
+ pid, mUserData->s.strName.c_str(), mData->mSession.mPID);
}
// create the mutable SessionMachine from the current machine
@@ -3154,25 +3385,25 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
/*
* Set the session state to Spawning to protect against subsequent
* attempts to open a session and to unregister the machine after
- * we leave the lock.
+ * we release the lock.
*/
SessionState_T origState = mData->mSession.mState;
mData->mSession.mState = SessionState_Spawning;
/*
- * Leave the lock before calling the client process -- it will call
- * Machine/SessionMachine methods. Leaving the lock here is quite safe
+ * Release the lock before calling the client process -- it will call
+ * Machine/SessionMachine methods. Releasing the lock here is quite safe
* because the state is Spawning, so that LaunchVMProcess() and
* LockMachine() calls will fail. This method, called before we
- * enter the lock again, will fail because of the wrong PID.
+ * acquire the lock again, will fail because of the wrong PID.
*
* Note that mData->mSession.mRemoteControls accessed outside
* the lock may not be modified when state is Spawning, so it's safe.
*/
- alock.leave();
+ alock.release();
LogFlowThisFunc(("Calling AssignMachine()...\n"));
- rc = pSessionControl->AssignMachine(sessionMachine);
+ rc = pSessionControl->AssignMachine(sessionMachine, lockType);
LogFlowThisFunc(("AssignMachine() returned %08X\n", rc));
/* The failure may occur w/o any error info (from RPC), so provide one */
@@ -3218,8 +3449,8 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
pSessionControl->Uninitialize();
}
- /* enter the lock again */
- alock.enter();
+ /* acquire the lock again */
+ alock.acquire();
/* Restore the session state */
mData->mSession.mState = origState;
@@ -3232,7 +3463,7 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
/** @todo Consider checking mData->mSession.mProgress for cancellation
* around here. */
- /* We don't reset mSession.mPid here because it is necessary for
+ /* We don't reset mSession.mPID here because it is necessary for
* SessionMachine::uninit() to reap the child process later. */
if (FAILED(rc))
@@ -3256,7 +3487,7 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
{
/* memorize PID of the directly opened session */
if (SUCCEEDED(rc))
- mData->mSession.mPid = pid;
+ mData->mSession.mPID = pid;
}
if (SUCCEEDED(rc))
@@ -3274,9 +3505,9 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
NOREF(unk);
}
- /* Leave the lock since SessionMachine::uninit() locks VirtualBox which
+ /* Release the lock since SessionMachine::uninit() locks VirtualBox which
* would break the lock order */
- alock.leave();
+ alock.release();
/* uninitialize the created session machine on failure */
if (FAILED(rc))
@@ -3287,9 +3518,9 @@ STDMETHODIMP Machine::LockMachine(ISession *aSession,
if (SUCCEEDED(rc))
{
/*
- * tell the client watcher thread to update the set of
- * machines that have open sessions
- */
+ * tell the client watcher thread to update the set of
+ * machines that have open sessions
+ */
mParent->updateClientWatcher();
if (oldState != SessionState_Locked)
@@ -3399,8 +3630,8 @@ STDMETHODIMP Machine::LaunchVMProcess(ISession *aSession,
mUserData->s.strName.c_str());
/* forcibly terminate the VM process */
- if (mData->mSession.mPid != NIL_RTPROCESS)
- RTProcTerminate(mData->mSession.mPid);
+ if (mData->mSession.mPID != NIL_RTPROCESS)
+ RTProcTerminate(mData->mSession.mPID);
/* signal the client watcher thread, as most likely the client has
* been terminated */
@@ -3469,15 +3700,12 @@ STDMETHODIMP Machine::AttachDevice(IN_BSTR aControllerName,
// request the host lock first, since might be calling Host methods for getting host drives;
// next, protect the media tree all the while we're in here, as well as our member variables
- AutoMultiWriteLock2 alock(mParent->host()->lockHandle(),
- this->lockHandle() COMMA_LOCKVAL_SRC_POS);
+ AutoMultiWriteLock2 alock(mParent->host(), this COMMA_LOCKVAL_SRC_POS);
AutoWriteLock treeLock(&mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
HRESULT rc = checkStateDependency(MutableStateDep);
if (FAILED(rc)) return rc;
- GuidList llRegistriesThatNeedSaving;
-
/// @todo NEWMEDIA implicit machine registration
if (!mData->mRegistered)
return setError(VBOX_E_INVALID_OBJECT_STATE,
@@ -3784,50 +4012,61 @@ STDMETHODIMP Machine::AttachDevice(IN_BSTR aControllerName,
// creating the diff image for the immutable, and the parent is not yet registered);
// put the parent in the machine registry then
mediumLock.release();
- addMediumToRegistry(medium, llRegistriesThatNeedSaving, &uuidRegistryParent);
+ treeLock.release();
+ alock.release();
+ addMediumToRegistry(medium);
+ alock.acquire();
+ treeLock.acquire();
mediumLock.acquire();
+ medium->getFirstRegistryMachineId(uuidRegistryParent);
}
rc = diff->init(mParent,
medium->getPreferredDiffFormat(),
strFullSnapshotFolder.append(RTPATH_SLASH_STR),
- uuidRegistryParent,
- &llRegistriesThatNeedSaving);
+ uuidRegistryParent);
if (FAILED(rc)) return rc;
/* Apply the normal locking logic to the entire chain. */
MediumLockList *pMediumLockList(new MediumLockList());
+ mediumLock.release();
+ treeLock.release();
rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
medium,
*pMediumLockList);
+ treeLock.acquire();
+ mediumLock.acquire();
if (SUCCEEDED(rc))
{
+ mediumLock.release();
+ treeLock.release();
rc = pMediumLockList->Lock();
+ treeLock.acquire();
+ mediumLock.acquire();
if (FAILED(rc))
setError(rc,
tr("Could not lock medium when creating diff '%s'"),
diff->getLocationFull().c_str());
else
{
- /* will leave the lock before the potentially lengthy operation, so
- * protect with the special state */
+ /* will release the lock before the potentially lengthy
+ * operation, so protect with the special state */
MachineState_T oldState = mData->mMachineState;
setMachineState(MachineState_SettingUp);
- mediumLock.leave();
- treeLock.leave();
- alock.leave();
+ mediumLock.release();
+ treeLock.release();
+ alock.release();
rc = medium->createDiffStorage(diff,
MediumVariant_Standard,
pMediumLockList,
NULL /* aProgress */,
- true /* aWait */,
- &llRegistriesThatNeedSaving);
+ true /* aWait */);
- alock.enter();
- treeLock.enter();
- mediumLock.enter();
+ alock.acquire();
+ treeLock.acquire();
+ mediumLock.acquire();
setMachineState(oldState);
}
@@ -3858,6 +4097,7 @@ STDMETHODIMP Machine::AttachDevice(IN_BSTR aControllerName,
false /* fPassthrough */,
false /* fTempEject */,
false /* fNonRotational */,
+ false /* fDiscard */,
Utf8Str::Empty);
if (FAILED(rc)) return rc;
@@ -3869,9 +4109,11 @@ STDMETHODIMP Machine::AttachDevice(IN_BSTR aControllerName,
if (FAILED(rc)) return rc;
mediumLock.release();
- addMediumToRegistry(medium,
- llRegistriesThatNeedSaving,
- NULL /* Guid *puuid */);
+ treeLock.release();
+ alock.release();
+ addMediumToRegistry(medium);
+ alock.acquire();
+ treeLock.acquire();
mediumLock.acquire();
}
@@ -3881,13 +4123,13 @@ STDMETHODIMP Machine::AttachDevice(IN_BSTR aControllerName,
mMediaData->mAttachments.push_back(attachment);
mediumLock.release();
- treeLock.leave();
+ treeLock.release();
alock.release();
if (fHotplug)
rc = onStorageDeviceChange(attachment, FALSE /* aRemove */);
- mParent->saveRegistries(llRegistriesThatNeedSaving);
+ mParent->saveModifiedRegistries();
return rc;
}
@@ -3903,8 +4145,6 @@ STDMETHODIMP Machine::DetachDevice(IN_BSTR aControllerName, LONG aControllerPort
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- GuidList llRegistriesThatNeedSaving;
-
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = checkStateDependency(MutableStateDep);
@@ -3949,19 +4189,18 @@ STDMETHODIMP Machine::DetachDevice(IN_BSTR aControllerName, LONG aControllerPort
*/
if (fHotplug)
{
- alock.leave();
+ alock.release();
rc = onStorageDeviceChange(pAttach, TRUE /* aRemove */);
- alock.enter();
+ alock.acquire();
}
if (FAILED(rc)) return rc;
/* If we are here everything went well and we can delete the implicit now. */
- rc = detachDevice(pAttach, alock, NULL /* pSnapshot */, &llRegistriesThatNeedSaving);
+ rc = detachDevice(pAttach, alock, NULL /* pSnapshot */);
alock.release();
- if (SUCCEEDED(rc))
- mParent->saveRegistries(llRegistriesThatNeedSaving);
+ mParent->saveModifiedRegistries();
return rc;
}
@@ -4100,6 +4339,65 @@ STDMETHODIMP Machine::NonRotationalDevice(IN_BSTR aControllerName, LONG aControl
return S_OK;
}
+STDMETHODIMP Machine::SetAutoDiscardForDevice(IN_BSTR aControllerName, LONG aControllerPort,
+ LONG aDevice, BOOL aDiscard)
+{
+ CheckComArgStrNotEmptyOrNull(aControllerName);
+
+ LogFlowThisFunc(("aControllerName=\"%ls\" aControllerPort=%d aDevice=%d aDiscard=%d\n",
+ aControllerName, aControllerPort, aDevice, aDiscard));
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ HRESULT rc = checkStateDependency(MutableStateDep);
+ if (FAILED(rc)) return rc;
+
+ AssertReturn(mData->mMachineState != MachineState_Saved, E_FAIL);
+
+ if (Global::IsOnlineOrTransient(mData->mMachineState))
+ return setError(VBOX_E_INVALID_VM_STATE,
+ tr("Invalid machine state: %s"),
+ Global::stringifyMachineState(mData->mMachineState));
+
+ MediumAttachment *pAttach = findAttachment(mMediaData->mAttachments,
+ aControllerName,
+ aControllerPort,
+ aDevice);
+ if (!pAttach)
+ return setError(VBOX_E_OBJECT_NOT_FOUND,
+ tr("No storage device attached to device slot %d on port %d of controller '%ls'"),
+ aDevice, aControllerPort, aControllerName);
+
+
+ setModified(IsModified_Storage);
+ mMediaData.backup();
+
+ AutoWriteLock attLock(pAttach COMMA_LOCKVAL_SRC_POS);
+
+ if (pAttach->getType() != DeviceType_HardDisk)
+ return setError(E_INVALIDARG,
+ tr("Setting the discard medium flag rejected as the device attached to device slot %d on port %d of controller '%ls' is not a hard disk"),
+ aDevice, aControllerPort, aControllerName);
+ pAttach->updateDiscard(!!aDiscard);
+
+ return S_OK;
+}
+
+STDMETHODIMP Machine::SetNoBandwidthGroupForDevice(IN_BSTR aControllerName, LONG aControllerPort,
+ LONG aDevice)
+{
+ int rc = S_OK;
+ LogFlowThisFunc(("aControllerName=\"%ls\" aControllerPort=%d aDevice=%d\n",
+ aControllerName, aControllerPort, aDevice));
+
+ rc = SetBandwidthGroupForDevice(aControllerName, aControllerPort, aDevice, NULL);
+
+ return rc;
+}
+
STDMETHODIMP Machine::SetBandwidthGroupForDevice(IN_BSTR aControllerName, LONG aControllerPort,
LONG aDevice, IBandwidthGroup *aBandwidthGroup)
{
@@ -4163,6 +4461,36 @@ STDMETHODIMP Machine::SetBandwidthGroupForDevice(IN_BSTR aControllerName, LONG a
return S_OK;
}
+STDMETHODIMP Machine::AttachDeviceWithoutMedium(IN_BSTR aControllerName,
+ LONG aControllerPort,
+ LONG aDevice,
+ DeviceType_T aType)
+{
+ HRESULT rc = S_OK;
+
+ LogFlowThisFunc(("aControllerName=\"%ls\" aControllerPort=%d aDevice=%d aType=%d aMedium=%p\n",
+ aControllerName, aControllerPort, aDevice, aType));
+
+ rc = AttachDevice(aControllerName, aControllerPort, aDevice, aType, NULL);
+
+ return rc;
+}
+
+
+
+STDMETHODIMP Machine::UnmountMedium(IN_BSTR aControllerName,
+ LONG aControllerPort,
+ LONG aDevice,
+ BOOL aForce)
+{
+ int rc = S_OK;
+ LogFlowThisFunc(("aControllerName=\"%ls\" aControllerPort=%d aDevice=%d",
+ aControllerName, aControllerPort, aForce));
+
+ rc = MountMedium(aControllerName, aControllerPort, aDevice, NULL, aForce);
+
+ return rc;
+}
STDMETHODIMP Machine::MountMedium(IN_BSTR aControllerName,
LONG aControllerPort,
@@ -4228,8 +4556,6 @@ STDMETHODIMP Machine::MountMedium(IN_BSTR aControllerName,
setModified(IsModified_Storage);
mMediaData.backup();
- GuidList llRegistriesThatNeedSaving;
-
{
// The backup operation makes the pAttach reference point to the
// old settings. Re-get the correct reference.
@@ -4237,7 +4563,6 @@ STDMETHODIMP Machine::MountMedium(IN_BSTR aControllerName,
aControllerName,
aControllerPort,
aDevice);
- AutoWriteLock attLock(pAttach COMMA_LOCKVAL_SRC_POS);
if (!oldmedium.isNull())
oldmedium->removeBackReference(mData->mUuid);
if (!pMedium.isNull())
@@ -4245,10 +4570,13 @@ STDMETHODIMP Machine::MountMedium(IN_BSTR aControllerName,
pMedium->addBackReference(mData->mUuid);
mediumLock.release();
- addMediumToRegistry(pMedium, llRegistriesThatNeedSaving, NULL /* Guid *puuid */ );
+ multiLock.release();
+ addMediumToRegistry(pMedium);
+ multiLock.acquire();
mediumLock.acquire();
}
+ AutoWriteLock attLock(pAttach COMMA_LOCKVAL_SRC_POS);
pAttach->updateMedium(pMedium);
}
@@ -4281,7 +4609,7 @@ STDMETHODIMP Machine::MountMedium(IN_BSTR aControllerName,
mediumLock.release();
multiLock.release();
- mParent->saveRegistries(llRegistriesThatNeedSaving);
+ mParent->saveModifiedRegistries();
return rc;
}
@@ -4351,7 +4679,12 @@ STDMETHODIMP Machine::GetParallelPort(ULONG slot, IParallelPort **port)
STDMETHODIMP Machine::GetNetworkAdapter(ULONG slot, INetworkAdapter **adapter)
{
CheckComArgOutPointerValid(adapter);
- CheckComArgExpr(slot, slot < RT_ELEMENTS(mNetworkAdapters));
+ /* Do not assert if slot is out of range, just return the advertised
+ status. testdriver/vbox.py triggers this in logVmInfo. */
+ if (slot >= mNetworkAdapters.size())
+ return setError(E_INVALIDARG,
+ tr("No network adapter in slot %RU32 (total %RU32 adapters)"),
+ slot, mNetworkAdapters.size());
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -4365,8 +4698,7 @@ STDMETHODIMP Machine::GetNetworkAdapter(ULONG slot, INetworkAdapter **adapter)
STDMETHODIMP Machine::GetExtraDataKeys(ComSafeArrayOut(BSTR, aKeys))
{
- if (ComSafeArrayOutIsNull(aKeys))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aKeys);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -4510,7 +4842,7 @@ STDMETHODIMP Machine::SaveSettings()
/* when there was auto-conversion, we want to save the file even if
* the VM is saved */
- HRESULT rc = checkStateDependency(MutableStateDep);
+ HRESULT rc = checkStateDependency(MutableOrSavedStateDep);
if (FAILED(rc)) return rc;
/* the settings file path may never be null */
@@ -4576,7 +4908,7 @@ STDMETHODIMP Machine::Unregister(CleanupMode_T cleanupMode,
// here because currently there may be no unregistered that are inaccessible
// (this state combination is not supported). Note releasing the caller and
// leaving the lock before calling uninit()
- alock.leave();
+ alock.release();
autoCaller.release();
uninit();
@@ -4679,7 +5011,7 @@ STDMETHODIMP Machine::Unregister(CleanupMode_T cleanupMode,
sfaMedia.detachTo(ComSafeArrayOutArg(aMedia));
mParent->unregisterMachine(this, id);
- // calls VirtualBox::saveSettings()
+ // calls VirtualBox::saveSettings() and VirtualBox::saveModifiedRegistries()
return S_OK;
}
@@ -4687,10 +5019,9 @@ STDMETHODIMP Machine::Unregister(CleanupMode_T cleanupMode,
struct Machine::DeleteTask
{
ComObjPtr<Machine> pMachine;
- RTCList< ComPtr<IMedium> > llMediums;
- std::list<Utf8Str> llFilesToDelete;
+ RTCList<ComPtr<IMedium> > llMediums;
+ StringsList llFilesToDelete;
ComObjPtr<Progress> pProgress;
- GuidList llRegistriesThatNeedSaving;
};
STDMETHODIMP Machine::Delete(ComSafeArrayIn(IMedium*, aMedia), IProgress **aProgress)
@@ -4842,13 +5173,10 @@ HRESULT Machine::deleteTaskWorker(DeleteTask &task)
LONG iRc;
rc = pProgress2->COMGETTER(ResultCode)(&iRc);
if (FAILED(rc)) throw rc;
+ /* If the thread of the progress object has an error, then
+ * retrieve the error info from there, or it'll be lost. */
if (FAILED(iRc))
- {
- /* If the thread of the progress object has an error, then
- * retrieve the error info from there, or it'll be lost. */
- ProgressErrorInfo info(pProgress2);
- throw setError(iRc, Utf8Str(info.getText()).c_str());
- }
+ throw setError(ProgressErrorInfo(pProgress2));
}
setMachineState(oldState);
alock.acquire();
@@ -4857,7 +5185,7 @@ HRESULT Machine::deleteTaskWorker(DeleteTask &task)
// (this includes saved states of the machine and snapshots and
// medium storage files from the IMedium list passed in, and the
// machine XML file)
- std::list<Utf8Str>::const_iterator it = task.llFilesToDelete.begin();
+ StringsList::const_iterator it = task.llFilesToDelete.begin();
while (it != task.llFilesToDelete.end())
{
const Utf8Str &strFile = *it;
@@ -4939,7 +5267,7 @@ HRESULT Machine::deleteTaskWorker(DeleteTask &task)
alock.release();
- mParent->saveRegistries(task.llRegistriesThatNeedSaving);
+ mParent->saveModifiedRegistries();
}
catch (HRESULT aRC) { rc = aRC; }
@@ -5010,7 +5338,7 @@ STDMETHODIMP Machine::CreateSharedFolder(IN_BSTR aName, IN_BSTR aHostPath, BOOL
mHWData->mSharedFolders.push_back(sharedFolder);
/* inform the direct session if any */
- alock.leave();
+ alock.release();
onSharedFolderChange();
return S_OK;
@@ -5037,7 +5365,7 @@ STDMETHODIMP Machine::RemoveSharedFolder(IN_BSTR aName)
mHWData->mSharedFolders.remove(sharedFolder);
/* inform the direct session if any */
- alock.leave();
+ alock.release();
onSharedFolderChange();
return S_OK;
@@ -5257,7 +5585,7 @@ HRESULT Machine::setGuestPropertyToService(IN_BSTR aName, IN_BSTR aValue,
}
if (found && SUCCEEDED(rc))
{
- if (*aValue)
+ if (aValue)
{
RTTIMESPEC time;
property.strValue = aValue;
@@ -5267,7 +5595,7 @@ HRESULT Machine::setGuestPropertyToService(IN_BSTR aName, IN_BSTR aValue,
mHWData->mGuestProperties.push_back(property);
}
}
- else if (SUCCEEDED(rc) && *aValue)
+ else if (SUCCEEDED(rc) && aValue)
{
RTTIMESPEC time;
setModified(IsModified_MachineData);
@@ -5365,6 +5693,11 @@ STDMETHODIMP Machine::SetGuestPropertyValue(IN_BSTR aName, IN_BSTR aValue)
return SetGuestProperty(aName, aValue, NULL);
}
+STDMETHODIMP Machine::DeleteGuestProperty(IN_BSTR aName)
+{
+ return SetGuestProperty(aName, NULL, NULL);
+}
+
#ifdef VBOX_WITH_GUEST_PROPS
/**
* Enumerate the guest properties in VBoxSVC's internal structures.
@@ -5593,7 +5926,7 @@ STDMETHODIMP Machine::AddStorageController(IN_BSTR aName,
ctrl.queryInterfaceTo(controller);
/* inform the direct session if any */
- alock.leave();
+ alock.release();
onStorageControllerChange();
return S_OK;
@@ -5687,7 +6020,7 @@ STDMETHODIMP Machine::SetStorageControllerBootable(IN_BSTR aName, BOOL fBootable
if (SUCCEEDED(rc))
{
/* inform the direct session if any */
- alock.leave();
+ alock.release();
onStorageControllerChange();
}
@@ -5710,16 +6043,29 @@ STDMETHODIMP Machine::RemoveStorageController(IN_BSTR aName)
rc = getStorageControllerByName(aName, ctrl, true /* aSetError */);
if (FAILED(rc)) return rc;
- /* We can remove the controller only if there is no device attached. */
- /* check if the device slot is already busy */
- for (MediaData::AttachmentList::const_iterator it = mMediaData->mAttachments.begin();
- it != mMediaData->mAttachments.end();
- ++it)
{
- if ((*it)->getControllerName() == aName)
- return setError(VBOX_E_OBJECT_IN_USE,
- tr("Storage controller named '%ls' has still devices attached"),
- aName);
+ /* find all attached devices to the appropriate storage controller and detach them all */
+ // make a temporary list because detachDevice invalidates iterators into
+ // mMediaData->mAttachments
+ MediaData::AttachmentList llAttachments2 = mMediaData->mAttachments;
+
+ for (MediaData::AttachmentList::iterator it = llAttachments2.begin();
+ it != llAttachments2.end();
+ ++it)
+ {
+ MediumAttachment *pAttachTemp = *it;
+
+ AutoCaller localAutoCaller(pAttachTemp);
+ if (FAILED(localAutoCaller.rc())) return localAutoCaller.rc();
+
+ AutoReadLock local_alock(pAttachTemp COMMA_LOCKVAL_SRC_POS);
+
+ if (pAttachTemp->getControllerName() == aName)
+ {
+ rc = detachDevice(pAttachTemp, alock, NULL);
+ if (FAILED(rc)) return rc;
+ }
+ }
}
/* We can remove it now. */
@@ -5731,30 +6077,56 @@ STDMETHODIMP Machine::RemoveStorageController(IN_BSTR aName)
mStorageControllers->remove(ctrl);
/* inform the direct session if any */
- alock.leave();
+ alock.release();
onStorageControllerChange();
return S_OK;
}
-STDMETHODIMP Machine::QuerySavedGuestSize(ULONG uScreenId, ULONG *puWidth, ULONG *puHeight)
+STDMETHODIMP Machine::QuerySavedGuestScreenInfo(ULONG uScreenId,
+ ULONG *puOriginX,
+ ULONG *puOriginY,
+ ULONG *puWidth,
+ ULONG *puHeight,
+ BOOL *pfEnabled)
{
LogFlowThisFunc(("\n"));
+ CheckComArgNotNull(puOriginX);
+ CheckComArgNotNull(puOriginY);
CheckComArgNotNull(puWidth);
CheckComArgNotNull(puHeight);
+ CheckComArgNotNull(pfEnabled);
+ uint32_t u32OriginX= 0;
+ uint32_t u32OriginY= 0;
uint32_t u32Width = 0;
uint32_t u32Height = 0;
+ uint16_t u16Flags = 0;
- int vrc = readSavedGuestSize(mSSData->strStateFilePath, uScreenId, &u32Width, &u32Height);
+ int vrc = readSavedGuestScreenInfo(mSSData->strStateFilePath, uScreenId,
+ &u32OriginX, &u32OriginY, &u32Width, &u32Height, &u16Flags);
if (RT_FAILURE(vrc))
+ {
+#ifdef RT_OS_WINDOWS
+ /* HACK: GUI sets *pfEnabled to 'true' and expects it to stay so if the API fails.
+ * This works with XPCOM. But Windows COM sets all output parameters to zero.
+ * So just assign fEnable to TRUE again.
+ * The right fix would be to change GUI API wrappers to make sure that parameters
+ * are changed only if API succeeds.
+ */
+ *pfEnabled = TRUE;
+#endif
return setError(VBOX_E_IPRT_ERROR,
tr("Saved guest size is not available (%Rrc)"),
vrc);
+ }
+ *puOriginX = u32OriginX;
+ *puOriginY = u32OriginY;
*puWidth = u32Width;
*puHeight = u32Height;
+ *pfEnabled = (u16Flags & VBVA_SCREEN_F_DISABLED) == 0;
return S_OK;
}
@@ -5890,22 +6262,34 @@ STDMETHODIMP Machine::ReadSavedThumbnailPNGToArray(ULONG aScreenId, ULONG *aWidt
*aWidth = u32Width;
*aHeight = u32Height;
+ HRESULT rc = S_OK;
uint8_t *pu8PNG = NULL;
uint32_t cbPNG = 0;
uint32_t cxPNG = 0;
uint32_t cyPNG = 0;
- DisplayMakePNG(pu8Data, u32Width, u32Height, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 0);
-
- com::SafeArray<BYTE> screenData(cbPNG);
- screenData.initFrom(pu8PNG, cbPNG);
- RTMemFree(pu8PNG);
+ vrc = DisplayMakePNG(pu8Data, u32Width, u32Height, &pu8PNG, &cbPNG, &cxPNG, &cyPNG, 0);
- screenData.detachTo(ComSafeArrayOutArg(aData));
+ if (RT_SUCCESS(vrc))
+ {
+ com::SafeArray<BYTE> screenData(cbPNG);
+ screenData.initFrom(pu8PNG, cbPNG);
+ if (pu8PNG)
+ RTMemFree(pu8PNG);
+ screenData.detachTo(ComSafeArrayOutArg(aData));
+ }
+ else
+ {
+ if (pu8PNG)
+ RTMemFree(pu8PNG);
+ return setError(VBOX_E_IPRT_ERROR,
+ tr("Could not convert screenshot to PNG (%Rrc)"),
+ vrc);
+ }
freeSavedDisplayScreenshot(pu8Data);
- return S_OK;
+ return rc;
}
STDMETHODIMP Machine::QuerySavedScreenshotPNGSize(ULONG aScreenId, ULONG *aSize, ULONG *aWidth, ULONG *aHeight)
@@ -6162,7 +6546,7 @@ STDMETHODIMP Machine::ReadLog(ULONG aIdx, LONG64 aOffset, LONG64 aSize, ComSafeA
* Currently this method doesn't attach device to the running VM,
* just makes sure it's plugged on next VM start.
*/
-STDMETHODIMP Machine::AttachHostPciDevice(LONG hostAddress, LONG desiredGuestAddress, BOOL /*tryToUnbind*/)
+STDMETHODIMP Machine::AttachHostPCIDevice(LONG hostAddress, LONG desiredGuestAddress, BOOL /*tryToUnbind*/)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -6184,12 +6568,12 @@ STDMETHODIMP Machine::AttachHostPciDevice(LONG hostAddress, LONG desiredGuestAdd
}
// check if device with this host PCI address already attached
- for (HWData::PciDeviceAssignmentList::iterator it = mHWData->mPciDeviceAssignments.begin();
- it != mHWData->mPciDeviceAssignments.end();
+ for (HWData::PCIDeviceAssignmentList::iterator it = mHWData->mPCIDeviceAssignments.begin();
+ it != mHWData->mPCIDeviceAssignments.end();
++it)
{
LONG iHostAddress = -1;
- ComPtr<PciDeviceAttachment> pAttach;
+ ComPtr<PCIDeviceAttachment> pAttach;
pAttach = *it;
pAttach->COMGETTER(HostAddress)(&iHostAddress);
if (iHostAddress == hostAddress)
@@ -6197,7 +6581,7 @@ STDMETHODIMP Machine::AttachHostPciDevice(LONG hostAddress, LONG desiredGuestAdd
tr("Device with host PCI address already attached to this VM"));
}
- ComObjPtr<PciDeviceAttachment> pda;
+ ComObjPtr<PCIDeviceAttachment> pda;
char name[32];
RTStrPrintf(name, sizeof(name), "host%02x:%02x.%x", (hostAddress>>8) & 0xff, (hostAddress & 0xf8) >> 3, hostAddress & 7);
@@ -6206,7 +6590,7 @@ STDMETHODIMP Machine::AttachHostPciDevice(LONG hostAddress, LONG desiredGuestAdd
pda->init(this, bname, hostAddress, desiredGuestAddress, TRUE);
setModified(IsModified_MachineData);
mHWData.backup();
- mHWData->mPciDeviceAssignments.push_back(pda);
+ mHWData->mPCIDeviceAssignments.push_back(pda);
}
return S_OK;
@@ -6216,12 +6600,12 @@ STDMETHODIMP Machine::AttachHostPciDevice(LONG hostAddress, LONG desiredGuestAdd
* Currently this method doesn't detach device from the running VM,
* just makes sure it's not plugged on next VM start.
*/
-STDMETHODIMP Machine::DetachHostPciDevice(LONG hostAddress)
+STDMETHODIMP Machine::DetachHostPCIDevice(LONG hostAddress)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- ComObjPtr<PciDeviceAttachment> pAttach;
+ ComObjPtr<PCIDeviceAttachment> pAttach;
bool fRemoved = false;
HRESULT rc;
@@ -6232,8 +6616,8 @@ STDMETHODIMP Machine::DetachHostPciDevice(LONG hostAddress)
rc = checkStateDependency(MutableStateDep);
if (FAILED(rc)) return rc;
- for (HWData::PciDeviceAssignmentList::iterator it = mHWData->mPciDeviceAssignments.begin();
- it != mHWData->mPciDeviceAssignments.end();
+ for (HWData::PCIDeviceAssignmentList::iterator it = mHWData->mPCIDeviceAssignments.begin();
+ it != mHWData->mPCIDeviceAssignments.end();
++it)
{
LONG iHostAddress = -1;
@@ -6243,7 +6627,7 @@ STDMETHODIMP Machine::DetachHostPciDevice(LONG hostAddress)
{
setModified(IsModified_MachineData);
mHWData.backup();
- mHWData->mPciDeviceAssignments.remove(pAttach);
+ mHWData->mPCIDeviceAssignments.remove(pAttach);
fRemoved = true;
break;
}
@@ -6261,7 +6645,7 @@ STDMETHODIMP Machine::DetachHostPciDevice(LONG hostAddress)
Bstr mid;
rc = this->COMGETTER(Id)(mid.asOutParam());
Assert(SUCCEEDED(rc));
- fireHostPciDevicePlugEvent(es, mid.raw(), false /* unplugged */, true /* success */, pAttach, NULL);
+ fireHostPCIDevicePlugEvent(es, mid.raw(), false /* unplugged */, true /* success */, pAttach, NULL);
}
return fRemoved ? S_OK : setError(VBOX_E_OBJECT_NOT_FOUND,
@@ -6270,7 +6654,7 @@ STDMETHODIMP Machine::DetachHostPciDevice(LONG hostAddress)
);
}
-STDMETHODIMP Machine::COMGETTER(PciDeviceAssignments)(ComSafeArrayOut(IPciDeviceAttachment *, aAssignments))
+STDMETHODIMP Machine::COMGETTER(PCIDeviceAssignments)(ComSafeArrayOut(IPCIDeviceAttachment *, aAssignments))
{
CheckComArgOutSafeArrayPointerValid(aAssignments);
@@ -6279,7 +6663,7 @@ STDMETHODIMP Machine::COMGETTER(PciDeviceAssignments)(ComSafeArrayOut(IPciDevice
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- SafeIfaceArray<IPciDeviceAttachment> assignments(mHWData->mPciDeviceAssignments);
+ SafeIfaceArray<IPCIDeviceAttachment> assignments(mHWData->mPCIDeviceAssignments);
assignments.detachTo(ComSafeArrayOutArg(aAssignments));
return S_OK;
@@ -6297,6 +6681,260 @@ STDMETHODIMP Machine::COMGETTER(BandwidthControl)(IBandwidthControl **aBandwidth
return S_OK;
}
+STDMETHODIMP Machine::COMGETTER(TracingEnabled)(BOOL *pfEnabled)
+{
+ CheckComArgOutPointerValid(pfEnabled);
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ *pfEnabled = mHWData->mDebugging.fTracingEnabled;
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMSETTER(TracingEnabled)(BOOL fEnabled)
+{
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = checkStateDependency(MutableStateDep);
+ if (SUCCEEDED(hrc))
+ {
+ hrc = mHWData.backupEx();
+ if (SUCCEEDED(hrc))
+ {
+ setModified(IsModified_MachineData);
+ mHWData->mDebugging.fTracingEnabled = fEnabled != FALSE;
+ }
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMGETTER(TracingConfig)(BSTR *pbstrConfig)
+{
+ CheckComArgOutPointerValid(pbstrConfig);
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = mHWData->mDebugging.strTracingConfig.cloneToEx(pbstrConfig);
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMSETTER(TracingConfig)(IN_BSTR bstrConfig)
+{
+ CheckComArgStr(bstrConfig);
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = checkStateDependency(MutableStateDep);
+ if (SUCCEEDED(hrc))
+ {
+ hrc = mHWData.backupEx();
+ if (SUCCEEDED(hrc))
+ {
+ hrc = mHWData->mDebugging.strTracingConfig.cloneEx(bstrConfig);
+ if (SUCCEEDED(hrc))
+ setModified(IsModified_MachineData);
+ }
+ }
+ }
+ return hrc;
+
+}
+
+STDMETHODIMP Machine::COMGETTER(AllowTracingToAccessVM)(BOOL *pfAllow)
+{
+ CheckComArgOutPointerValid(pfAllow);
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ *pfAllow = mHWData->mDebugging.fAllowTracingToAccessVM;
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMSETTER(AllowTracingToAccessVM)(BOOL fAllow)
+{
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = checkStateDependency(MutableStateDep);
+ if (SUCCEEDED(hrc))
+ {
+ hrc = mHWData.backupEx();
+ if (SUCCEEDED(hrc))
+ {
+ setModified(IsModified_MachineData);
+ mHWData->mDebugging.fAllowTracingToAccessVM = fAllow != FALSE;
+ }
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMGETTER(AutostartEnabled)(BOOL *pfEnabled)
+{
+ CheckComArgOutPointerValid(pfEnabled);
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ *pfEnabled = mHWData->mAutostart.fAutostartEnabled;
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMSETTER(AutostartEnabled)(BOOL fEnabled)
+{
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = checkStateDependency(MutableStateDep);
+ if ( SUCCEEDED(hrc)
+ && mHWData->mAutostart.fAutostartEnabled != !!fEnabled)
+ {
+ AutostartDb *autostartDb = mParent->getAutostartDb();
+ int vrc;
+
+ if (fEnabled)
+ vrc = autostartDb->addAutostartVM(mUserData->s.strName.c_str());
+ else
+ vrc = autostartDb->removeAutostartVM(mUserData->s.strName.c_str());
+
+ if (RT_SUCCESS(vrc))
+ {
+ hrc = mHWData.backupEx();
+ if (SUCCEEDED(hrc))
+ {
+ setModified(IsModified_MachineData);
+ mHWData->mAutostart.fAutostartEnabled = fEnabled != FALSE;
+ }
+ }
+ else if (vrc == VERR_NOT_SUPPORTED)
+ hrc = setError(VBOX_E_NOT_SUPPORTED,
+ tr("The VM autostart feature is not supported on this platform"));
+ else if (vrc == VERR_PATH_NOT_FOUND)
+ hrc = setError(E_FAIL,
+ tr("The path to the autostart database is not set"));
+ else
+ hrc = setError(E_UNEXPECTED,
+ tr("%s machine '%s' to the autostart database failed with %Rrc"),
+ fEnabled ? "Adding" : "Removing",
+ mUserData->s.strName.c_str(), vrc);
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMGETTER(AutostartDelay)(ULONG *puDelay)
+{
+ CheckComArgOutPointerValid(puDelay);
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ *puDelay = mHWData->mAutostart.uAutostartDelay;
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMSETTER(AutostartDelay)(ULONG uDelay)
+{
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = checkStateDependency(MutableStateDep);
+ if (SUCCEEDED(hrc))
+ {
+ hrc = mHWData.backupEx();
+ if (SUCCEEDED(hrc))
+ {
+ setModified(IsModified_MachineData);
+ mHWData->mAutostart.uAutostartDelay = uDelay;
+ }
+ }
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMGETTER(AutostopType)(AutostopType_T *penmAutostopType)
+{
+ CheckComArgOutPointerValid(penmAutostopType);
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ *penmAutostopType = mHWData->mAutostart.enmAutostopType;
+ }
+ return hrc;
+}
+
+STDMETHODIMP Machine::COMSETTER(AutostopType)(AutostopType_T enmAutostopType)
+{
+ AutoCaller autoCaller(this);
+ HRESULT hrc = autoCaller.rc();
+ if (SUCCEEDED(hrc))
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ hrc = checkStateDependency(MutableStateDep);
+ if ( SUCCEEDED(hrc)
+ && mHWData->mAutostart.enmAutostopType != enmAutostopType)
+ {
+ AutostartDb *autostartDb = mParent->getAutostartDb();
+ int vrc;
+
+ if (enmAutostopType != AutostopType_Disabled)
+ vrc = autostartDb->addAutostopVM(mUserData->s.strName.c_str());
+ else
+ vrc = autostartDb->removeAutostopVM(mUserData->s.strName.c_str());
+
+ if (RT_SUCCESS(vrc))
+ {
+ hrc = mHWData.backupEx();
+ if (SUCCEEDED(hrc))
+ {
+ setModified(IsModified_MachineData);
+ mHWData->mAutostart.enmAutostopType = enmAutostopType;
+ }
+ }
+ else if (vrc == VERR_NOT_SUPPORTED)
+ hrc = setError(VBOX_E_NOT_SUPPORTED,
+ tr("The VM autostop feature is not supported on this platform"));
+ else if (vrc == VERR_PATH_NOT_FOUND)
+ hrc = setError(E_FAIL,
+ tr("The path to the autostart database is not set"));
+ else
+ hrc = setError(E_UNEXPECTED,
+ tr("%s machine '%s' to the autostop database failed with %Rrc"),
+ enmAutostopType != AutostopType_Disabled ? "Adding" : "Removing",
+ mUserData->s.strName.c_str(), vrc);
+ }
+ }
+ return hrc;
+}
+
+
STDMETHODIMP Machine::CloneTo(IMachine *pTarget, CloneMode_T mode, ComSafeArrayIn(CloneOptions_T, options), IProgress **pProgress)
{
LogFlowFuncEnter();
@@ -6672,7 +7310,6 @@ HRESULT Machine::launchVMProcess(IInternalSessionControl *aControl,
Utf8Str idStr = mData->mUuid.toString();
const char * args[] = {szPath, "--comment", mUserData->s.strName.c_str(), "--startvm", idStr.c_str(), 0 };
- fprintf(stderr, "SDL=%s\n", szPath);
vrc = RTProcCreate(szPath, args, env, 0, &pid);
}
#else /* !VBOX_WITH_VBOXSDL */
@@ -6713,11 +7350,11 @@ HRESULT Machine::launchVMProcess(IInternalSessionControl *aControl,
}
vrc = RTProcCreate(szPath, args, env,
#ifdef RT_OS_WINDOWS
- RTPROC_FLAGS_NO_WINDOW,
+ RTPROC_FLAGS_NO_WINDOW
#else
- 0,
+ 0
#endif
- &pid);
+ , &pid);
}
#else /* !VBOX_WITH_HEADLESS */
if (0)
@@ -6741,9 +7378,9 @@ HRESULT Machine::launchVMProcess(IInternalSessionControl *aControl,
LogFlowThisFunc(("launched.pid=%d(0x%x)\n", pid, pid));
/*
- * Note that we don't leave the lock here before calling the client,
+ * Note that we don't release the lock here before calling the client,
* because it doesn't need to call us back if called with a NULL argument.
- * Leaving the lock here is dangerous because we didn't prepare the
+ * Releasing the lock here is dangerous because we didn't prepare the
* launch data yet, but the client we've just started may happen to be
* too fast and call openSession() that will fail (because of PID, etc.),
* so that the Machine will never get out of the Spawning session state.
@@ -6751,7 +7388,7 @@ HRESULT Machine::launchVMProcess(IInternalSessionControl *aControl,
/* inform the session that it will be a remote one */
LogFlowThisFunc(("Calling AssignMachine (NULL)...\n"));
- HRESULT rc = aControl->AssignMachine(NULL);
+ HRESULT rc = aControl->AssignMachine(NULL, LockType_Write);
LogFlowThisFunc(("AssignMachine (NULL) returned %08X\n", rc));
if (FAILED(rc))
@@ -6764,10 +7401,10 @@ HRESULT Machine::launchVMProcess(IInternalSessionControl *aControl,
}
/* attach launch data to the machine */
- Assert(mData->mSession.mPid == NIL_RTPROCESS);
+ Assert(mData->mSession.mPID == NIL_RTPROCESS);
mData->mSession.mRemoteControls.push_back(aControl);
mData->mSession.mProgress = aProgress;
- mData->mSession.mPid = pid;
+ mData->mSession.mPID = pid;
mData->mSession.mState = SessionState_Spawning;
mData->mSession.mType = strType;
@@ -6866,8 +7503,8 @@ bool Machine::isSessionSpawning()
/* Additional session data */
if (aPID != NULL)
{
- AssertReturn(mData->mSession.mPid != NIL_RTPROCESS, false);
- *aPID = mData->mSession.mPid;
+ AssertReturn(mData->mSession.mPID != NIL_RTPROCESS, false);
+ *aPID = mData->mSession.mPID;
}
#endif
return true;
@@ -6922,11 +7559,11 @@ bool Machine::checkForSpawnFailure()
#else
/* PID not yet initialized, skip check. */
- if (mData->mSession.mPid == NIL_RTPROCESS)
+ if (mData->mSession.mPID == NIL_RTPROCESS)
return false;
RTPROCSTATUS status;
- int vrc = ::RTProcWait(mData->mSession.mPid, RTPROCWAIT_FLAGS_NOBLOCK,
+ int vrc = ::RTProcWait(mData->mSession.mPID, RTPROCWAIT_FLAGS_NOBLOCK,
&status);
if (vrc != VERR_PROCESS_RUNNING)
@@ -6974,8 +7611,8 @@ bool Machine::checkForSpawnFailure()
mData->mSession.mProgress.setNull();
}
- mParent->addProcessToReap(mData->mSession.mPid);
- mData->mSession.mPid = NIL_RTPROCESS;
+ mParent->addProcessToReap(mData->mSession.mPID);
+ mData->mSession.mPID = NIL_RTPROCESS;
mParent->onSessionStateChange(mData->mUuid, SessionState_Unlocked);
return true;
@@ -7156,6 +7793,10 @@ void Machine::releaseStateDependency()
* returned. This is useful in setters which allow changing machine
* properties when it is in the saved state.
*
+ * When @a aDepType is OfflineStateDep, this method returns S_OK if the
+ * state is one of the 4 offline states (PoweredOff, Saved, Teleported,
+ * Aborted).
+ *
* @param aDepType Dependency type to check.
*
* @note Non Machine based classes should use #addStateDependency() and
@@ -7208,6 +7849,22 @@ HRESULT Machine::checkStateDependency(StateDependency aDepType)
Global::stringifyMachineState(mData->mMachineState));
break;
}
+ case OfflineStateDep:
+ {
+ if ( mData->mRegistered
+ && ( !isSessionMachine()
+ || ( mData->mMachineState != MachineState_PoweredOff
+ && mData->mMachineState != MachineState_Saved
+ && mData->mMachineState != MachineState_Aborted
+ && mData->mMachineState != MachineState_Teleported
+ )
+ )
+ )
+ return setError(VBOX_E_INVALID_VM_STATE,
+ tr("The machine is not offline (state is %s)"),
+ Global::stringifyMachineState(mData->mMachineState));
+ break;
+ }
}
return S_OK;
@@ -7272,7 +7929,8 @@ HRESULT Machine::initDataAndChildObjects()
mUSBController->init(this);
/* create associated network adapter objects */
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); slot ++)
+ mNetworkAdapters.resize(Global::getMaxNetworkAdapters(mHWData->mChipsetType));
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
{
unconst(mNetworkAdapters[slot]).createObject();
mNetworkAdapters[slot]->init(this, slot);
@@ -7308,7 +7966,7 @@ void Machine::uninitDataAndChildObjects()
unconst(mBandwidthControl).setNull();
}
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); slot++)
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
{
if (mNetworkAdapters[slot])
{
@@ -7359,13 +8017,13 @@ void Machine::uninitDataAndChildObjects()
unconst(mBIOSSettings).setNull();
}
- /* Deassociate hard disks (only when a real Machine or a SnapshotMachine
+ /* Deassociate media (only when a real Machine or a SnapshotMachine
* instance is uninitialized; SessionMachine instances refer to real
- * Machine hard disks). This is necessary for a clean re-initialization of
+ * Machine media). This is necessary for a clean re-initialization of
* the VM after successfully re-checking the accessibility state. Note
* that in case of normal Machine or SnapshotMachine uninitialization (as
- * a result of unregistering or deleting the snapshot), outdated hard
- * disk attachments will already be uninitialized and deleted, so this
+ * a result of unregistering or deleting the snapshot), outdated media
+ * attachments will already be uninitialized and deleted, so this
* code will not affect them. */
if ( !!mMediaData
&& (!isSessionMachine())
@@ -7375,10 +8033,10 @@ void Machine::uninitDataAndChildObjects()
it != mMediaData->mAttachments.end();
++it)
{
- ComObjPtr<Medium> hd = (*it)->getMedium();
- if (hd.isNull())
+ ComObjPtr<Medium> pMedium = (*it)->getMedium();
+ if (pMedium.isNull())
continue;
- HRESULT rc = hd->removeBackReference(mData->mUuid, getSnapshotId());
+ HRESULT rc = pMedium->removeBackReference(mData->mUuid, getSnapshotId());
AssertComRC(rc);
}
}
@@ -7388,7 +8046,7 @@ void Machine::uninitDataAndChildObjects()
// clean up the snapshots list (Snapshot::uninit() will handle the snapshot's children recursively)
if (mData->mFirstSnapshot)
{
- // snapshots tree is protected by media write lock; strictly
+ // snapshots tree is protected by machine write lock; strictly
// this isn't necessary here since we're deleting the entire
// machine, but otherwise we assert in Snapshot::uninit()
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -7458,11 +8116,11 @@ void Machine::ensureNoStateDependencies()
* it */
RTSemEventMultiReset(mData->mMachineStateDepsSem);
- alock.leave();
+ alock.release();
RTSemEventMultiWait(mData->mMachineStateDepsSem, RT_INDEFINITE_WAIT);
- alock.enter();
+ alock.acquire();
-- mData->mMachineStateChangePending;
}
@@ -7640,7 +8298,7 @@ HRESULT Machine::loadMachineDataFromSettings(const settings::MachineConfigFile &
}
// hardware data
- rc = loadHardware(config.hardwareMachine);
+ rc = loadHardware(config.hardwareMachine, &config.debugging, &config.autostart);
if (FAILED(rc)) return rc;
// load storage controllers
@@ -7708,11 +8366,13 @@ HRESULT Machine::loadSnapshot(const settings::Snapshot &data,
/* create a snapshot machine object */
ComObjPtr<SnapshotMachine> pSnapshotMachine;
pSnapshotMachine.createObject();
- rc = pSnapshotMachine->init(this,
- data.hardware,
- data.storage,
- data.uuid.ref(),
- strStateFile);
+ rc = pSnapshotMachine->initFromSettings(this,
+ data.hardware,
+ &data.debugging,
+ &data.autostart,
+ data.storage,
+ data.uuid.ref(),
+ strStateFile);
if (FAILED(rc)) return rc;
/* create a snapshot object */
@@ -7755,9 +8415,14 @@ HRESULT Machine::loadSnapshot(const settings::Snapshot &data,
}
/**
- * @param aNode <Hardware> node.
+ * Loads settings into mHWData.
+ *
+ * @param data Reference to the hardware settings.
+ * @param pDbg Pointer to the debugging settings.
+ * @param pAutostart Pointer to the autostart settings.
*/
-HRESULT Machine::loadHardware(const settings::Hardware &data)
+HRESULT Machine::loadHardware(const settings::Hardware &data, const settings::Debugging *pDbg,
+ const settings::Autostart *pAutostart)
{
AssertReturn(!isSessionMachine(), E_FAIL);
@@ -7857,12 +8522,16 @@ HRESULT Machine::loadHardware(const settings::Hardware &data)
mHWData->mMonitorCount = data.cMonitors;
mHWData->mAccelerate3DEnabled = data.fAccelerate3D;
mHWData->mAccelerate2DVideoEnabled = data.fAccelerate2DVideo;
+ mHWData->mVideoCaptureWidth = data.ulVideoCaptureHorzRes;
+ mHWData->mVideoCaptureHeight = data.ulVideoCaptureVertRes;
+ mHWData->mVideoCaptureEnabled = false; /* @todo r=klaus restore to data.fVideoCaptureEnabled */
+ mHWData->mVideoCaptureFile = data.strVideoCaptureFile;
mHWData->mFirmwareType = data.firmwareType;
- mHWData->mPointingHidType = data.pointingHidType;
- mHWData->mKeyboardHidType = data.keyboardHidType;
+ mHWData->mPointingHIDType = data.pointingHIDType;
+ mHWData->mKeyboardHIDType = data.keyboardHIDType;
mHWData->mChipsetType = data.chipsetType;
mHWData->mEmulatedUSBCardReaderEnabled = data.fEmulatedUSBCardReader;
- mHWData->mHpetEnabled = data.fHpetEnabled;
+ mHWData->mHPETEnabled = data.fHPETEnabled;
/* VRDEServer */
rc = mVRDEServer->loadSettings(data.vrdeSettings);
@@ -7881,6 +8550,19 @@ HRESULT Machine::loadHardware(const settings::Hardware &data)
if (FAILED(rc)) return rc;
// network adapters
+ uint32_t newCount = Global::getMaxNetworkAdapters(mHWData->mChipsetType);
+ uint32_t oldCount = mNetworkAdapters.size();
+ if (newCount > oldCount)
+ {
+ mNetworkAdapters.resize(newCount);
+ for (ULONG slot = oldCount; slot < mNetworkAdapters.size(); slot++)
+ {
+ unconst(mNetworkAdapters[slot]).createObject();
+ mNetworkAdapters[slot]->init(this, slot);
+ }
+ }
+ else if (newCount < oldCount)
+ mNetworkAdapters.resize(newCount);
for (settings::NetworkAdaptersList::const_iterator it = data.llNetworkAdapters.begin();
it != data.llNetworkAdapters.end();
++it)
@@ -7888,7 +8570,7 @@ HRESULT Machine::loadHardware(const settings::Hardware &data)
const settings::NetworkAdapter &nic = *it;
/* slot unicity is guaranteed by XML Schema */
- AssertBreak(nic.ulSlot < RT_ELEMENTS(mNetworkAdapters));
+ AssertBreak(nic.ulSlot < mNetworkAdapters.size());
rc = mNetworkAdapters[nic.ulSlot]->loadSettings(mBandwidthControl, nic);
if (FAILED(rc)) return rc;
}
@@ -7952,26 +8634,34 @@ HRESULT Machine::loadHardware(const settings::Hardware &data)
// Clipboard
mHWData->mClipboardMode = data.clipboardMode;
+ // drag'n'drop
+ mHWData->mDragAndDropMode = data.dragAndDropMode;
+
// guest settings
mHWData->mMemoryBalloonSize = data.ulMemoryBalloonSize;
// IO settings
- mHWData->mIoCacheEnabled = data.ioSettings.fIoCacheEnabled;
- mHWData->mIoCacheSize = data.ioSettings.ulIoCacheSize;
+ mHWData->mIOCacheEnabled = data.ioSettings.fIOCacheEnabled;
+ mHWData->mIOCacheSize = data.ioSettings.ulIOCacheSize;
// Host PCI devices
- for (settings::HostPciDeviceAttachmentList::const_iterator it = data.pciAttachments.begin();
+ for (settings::HostPCIDeviceAttachmentList::const_iterator it = data.pciAttachments.begin();
it != data.pciAttachments.end();
++it)
{
- const settings::HostPciDeviceAttachment &hpda = *it;
- ComObjPtr<PciDeviceAttachment> pda;
+ const settings::HostPCIDeviceAttachment &hpda = *it;
+ ComObjPtr<PCIDeviceAttachment> pda;
pda.createObject();
pda->loadSettings(this, hpda);
- mHWData->mPciDeviceAssignments.push_back(pda);
+ mHWData->mPCIDeviceAssignments.push_back(pda);
}
+ /*
+ * (The following isn't really real hardware, but it lives in HWData
+ * for reasons of convenience.)
+ */
+
#ifdef VBOX_WITH_GUEST_PROPS
/* Guest properties (optional) */
for (settings::GuestPropertiesList::const_iterator it = data.llGuestProperties.begin();
@@ -7981,12 +8671,18 @@ HRESULT Machine::loadHardware(const settings::Hardware &data)
const settings::GuestProperty &prop = *it;
uint32_t fFlags = guestProp::NILFLAG;
guestProp::validateFlags(prop.strFlags.c_str(), &fFlags);
- HWData::GuestProperty property = { prop.strName, prop.strValue, prop.timestamp, fFlags };
+ HWData::GuestProperty property = { prop.strName, prop.strValue, (LONG64) prop.timestamp, fFlags };
mHWData->mGuestProperties.push_back(property);
}
mHWData->mGuestPropertyNotificationPatterns = data.strNotificationPatterns;
#endif /* VBOX_WITH_GUEST_PROPS defined */
+
+ rc = loadDebugging(pDbg);
+ if (FAILED(rc))
+ return rc;
+
+ mHWData->mAutostart = *pAutostart;
}
catch(std::bad_alloc &)
{
@@ -7998,6 +8694,19 @@ HRESULT Machine::loadHardware(const settings::Hardware &data)
}
/**
+ * Called from Machine::loadHardware() to load the debugging settings of the
+ * machine.
+ *
+ * @param pDbg Pointer to the settings.
+ */
+HRESULT Machine::loadDebugging(const settings::Debugging *pDbg)
+{
+ mHWData->mDebugging = *pDbg;
+ /* no more processing currently required, this will probably change. */
+ return S_OK;
+}
+
+/**
* Called from loadMachineDataFromSettings() for the storage controller data, including media.
*
* @param data
@@ -8049,10 +8758,10 @@ HRESULT Machine::loadStorageControllers(const settings::Storage &data,
/* Set IDE emulation settings (only for AHCI controller). */
if (ctlData.controllerType == StorageControllerType_IntelAhci)
{
- if ( (FAILED(rc = pCtl->SetIDEEmulationPort(0, ctlData.lIDE0MasterEmulationPort)))
- || (FAILED(rc = pCtl->SetIDEEmulationPort(1, ctlData.lIDE0SlaveEmulationPort)))
- || (FAILED(rc = pCtl->SetIDEEmulationPort(2, ctlData.lIDE1MasterEmulationPort)))
- || (FAILED(rc = pCtl->SetIDEEmulationPort(3, ctlData.lIDE1SlaveEmulationPort)))
+ if ( (FAILED(rc = pCtl->setIDEEmulationPort(0, ctlData.lIDE0MasterEmulationPort)))
+ || (FAILED(rc = pCtl->setIDEEmulationPort(1, ctlData.lIDE0SlaveEmulationPort)))
+ || (FAILED(rc = pCtl->setIDEEmulationPort(2, ctlData.lIDE1MasterEmulationPort)))
+ || (FAILED(rc = pCtl->setIDEEmulationPort(3, ctlData.lIDE1SlaveEmulationPort)))
)
return rc;
}
@@ -8263,6 +8972,7 @@ HRESULT Machine::loadStorageDevices(StorageController *aStorageController,
dev.fPassThrough,
dev.fTempEject,
dev.fNonRotational,
+ dev.fDiscard,
pBwGroup.isNull() ? Utf8Str::Empty : pBwGroup->getName());
if (FAILED(rc)) break;
@@ -8450,10 +9160,13 @@ HRESULT Machine::prepareSaveSettings(bool *pfNeedsGlobalSaveSettings)
bool fSettingsFileIsNew = !mData->pMachineConfigFile->fileExists();
+ /// @todo need to handle primary group change, too
+
/* attempt to rename the settings file if machine name is changed */
if ( mUserData->s.fNameSync
&& mUserData.isBackedUp()
- && mUserData.backedUpData()->s.strName != mUserData->s.strName
+ && ( mUserData.backedUpData()->s.strName != mUserData->s.strName
+ || mUserData.backedUpData()->s.llGroups.front() != mUserData->s.llGroups.front())
)
{
bool dirRenamed = false;
@@ -8469,18 +9182,37 @@ HRESULT Machine::prepareSaveSettings(bool *pfNeedsGlobalSaveSettings)
Utf8Str name = mUserData.backedUpData()->s.strName;
Utf8Str newName = mUserData->s.strName;
+ Utf8Str group = mUserData.backedUpData()->s.llGroups.front();
+ if (group == "/")
+ group.setNull();
+ Utf8Str newGroup = mUserData->s.llGroups.front();
+ if (newGroup == "/")
+ newGroup.setNull();
configFile = mData->m_strConfigFileFull;
- /* first, rename the directory if it matches the machine name */
+ /* first, rename the directory if it matches the group and machine name */
+ Utf8Str groupPlusName = Utf8StrFmt("%s%c%s",
+ group.c_str(), RTPATH_DELIMITER, name.c_str());
+ /** @todo hack, make somehow use of ComposeMachineFilename */
+ if (mUserData->s.fDirectoryIncludesUUID)
+ groupPlusName += Utf8StrFmt(" (%RTuuid)", mData->mUuid.raw());
+ Utf8Str newGroupPlusName = Utf8StrFmt("%s%c%s",
+ newGroup.c_str(), RTPATH_DELIMITER, newName.c_str());
+ /** @todo hack, make somehow use of ComposeMachineFilename */
+ if (mUserData->s.fDirectoryIncludesUUID)
+ newGroupPlusName += Utf8StrFmt(" (%RTuuid)", mData->mUuid.raw());
configDir = configFile;
configDir.stripFilename();
newConfigDir = configDir;
- if (!strcmp(RTPathFilename(configDir.c_str()), name.c_str()))
+ if ( configDir.length() >= groupPlusName.length()
+ && !RTPathCompare(configDir.substr(configDir.length() - groupPlusName.length(), groupPlusName.length()).c_str(), groupPlusName.c_str()))
{
- newConfigDir.stripFilename();
- newConfigDir.append(RTPATH_DELIMITER);
- newConfigDir.append(newName);
+ newConfigDir = newConfigDir.substr(0, configDir.length() - groupPlusName.length());
+ Utf8Str newConfigBaseDir(newConfigDir);
+ newConfigDir.append(newGroupPlusName);
+ /* consistency: use \ if appropriate on the platform */
+ RTPathChangeToDosSlashes(newConfigDir.mutableRaw(), false);
/* new dir and old dir cannot be equal here because of 'if'
* above and because name != newName */
Assert(configDir != newConfigDir);
@@ -8488,6 +9220,15 @@ HRESULT Machine::prepareSaveSettings(bool *pfNeedsGlobalSaveSettings)
{
/* perform real rename only if the machine is not new */
vrc = RTPathRename(configDir.c_str(), newConfigDir.c_str(), 0);
+ if ( vrc == VERR_FILE_NOT_FOUND
+ || vrc == VERR_PATH_NOT_FOUND)
+ {
+ /* create the parent directory, then retry renaming */
+ Utf8Str parent(newConfigDir);
+ parent.stripFilename();
+ (void)RTDirCreateFullPath(parent.c_str(), 0700);
+ vrc = RTPathRename(configDir.c_str(), newConfigDir.c_str(), 0);
+ }
if (RT_FAILURE(vrc))
{
rc = setError(E_FAIL,
@@ -8497,6 +9238,16 @@ HRESULT Machine::prepareSaveSettings(bool *pfNeedsGlobalSaveSettings)
vrc);
break;
}
+ /* delete subdirectories which are no longer needed */
+ Utf8Str dir(configDir);
+ dir.stripFilename();
+ while (dir != newConfigBaseDir && dir != ".")
+ {
+ vrc = RTDirRemove(dir.c_str());
+ if (RT_FAILURE(vrc))
+ break;
+ dir.stripFilename();
+ }
dirRenamed = true;
}
}
@@ -8729,7 +9480,7 @@ HRESULT Machine::saveSettings(bool *pfNeedsGlobalSaveSettings,
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
if (fNeedsWrite || (aFlags & SaveS_InformCallbacksAnyway))
@@ -8813,7 +9564,7 @@ void Machine::copyMachineDataToSettings(settings::MachineConfigFile &config)
config.fAborted = (mData->mMachineState == MachineState_Aborted);
/// @todo Live Migration: config.fTeleported = (mData->mMachineState == MachineState_Teleported);
- HRESULT rc = saveHardware(config.hardwareMachine);
+ HRESULT rc = saveHardware(config.hardwareMachine, &config.debugging, &config.autostart);
if (FAILED(rc)) throw rc;
rc = saveStorageControllers(config.storageMachine);
@@ -8876,7 +9627,7 @@ HRESULT Machine::saveAllSnapshots(settings::MachineConfigFile &config)
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
return rc;
@@ -8886,9 +9637,14 @@ HRESULT Machine::saveAllSnapshots(settings::MachineConfigFile &config)
* Saves the VM hardware configuration. It is assumed that the
* given node is empty.
*
- * @param aNode <Hardware> node to save the VM hardware configuration to.
+ * @param data Reference to the settings object for the hardware config.
+ * @param pDbg Pointer to the settings object for the debugging config
+ * which happens to live in mHWData.
+ * @param pAutostart Pointer to the settings object for the autostart config
+ * which happens to live in mHWData.
*/
-HRESULT Machine::saveHardware(settings::Hardware &data)
+HRESULT Machine::saveHardware(settings::Hardware &data, settings::Debugging *pDbg,
+ settings::Autostart *pAutostart)
{
HRESULT rc = S_OK;
@@ -8953,8 +9709,8 @@ HRESULT Machine::saveHardware(settings::Hardware &data)
data.firmwareType = mHWData->mFirmwareType;
// HID
- data.pointingHidType = mHWData->mPointingHidType;
- data.keyboardHidType = mHWData->mKeyboardHidType;
+ data.pointingHIDType = mHWData->mPointingHIDType;
+ data.keyboardHIDType = mHWData->mKeyboardHIDType;
// chipset
data.chipsetType = mHWData->mChipsetType;
@@ -8962,7 +9718,7 @@ HRESULT Machine::saveHardware(settings::Hardware &data)
data.fEmulatedUSBCardReader = !!mHWData->mEmulatedUSBCardReaderEnabled;
// HPET
- data.fHpetEnabled = !!mHWData->mHpetEnabled;
+ data.fHPETEnabled = !!mHWData->mHPETEnabled;
// boot order
data.mapBootOrder.clear();
@@ -8976,6 +9732,10 @@ HRESULT Machine::saveHardware(settings::Hardware &data)
data.cMonitors = mHWData->mMonitorCount;
data.fAccelerate3D = !!mHWData->mAccelerate3DEnabled;
data.fAccelerate2DVideo = !!mHWData->mAccelerate2DVideoEnabled;
+ data.ulVideoCaptureHorzRes = mHWData->mVideoCaptureWidth;
+ data.ulVideoCaptureVertRes = mHWData->mVideoCaptureHeight;
+ data.fVideoCaptureEnabled = !!mHWData->mVideoCaptureEnabled;
+ data.strVideoCaptureFile = mHWData->mVideoCaptureFile;
/* VRDEServer settings (optional) */
rc = mVRDEServer->saveSettings(data.vrdeSettings);
@@ -8990,17 +9750,23 @@ HRESULT Machine::saveHardware(settings::Hardware &data)
if (FAILED(rc)) throw rc;
/* Network adapters (required) */
+ uint32_t uMaxNICs = RT_MIN(Global::getMaxNetworkAdapters(mHWData->mChipsetType), mNetworkAdapters.size());
data.llNetworkAdapters.clear();
- for (ULONG slot = 0;
- slot < RT_ELEMENTS(mNetworkAdapters);
- ++slot)
+ /* Write out only the nominal number of network adapters for this
+ * chipset type. Since Machine::commit() hasn't been called there
+ * may be extra NIC settings in the vector. */
+ for (ULONG slot = 0; slot < uMaxNICs; ++slot)
{
settings::NetworkAdapter nic;
nic.ulSlot = slot;
- rc = mNetworkAdapters[slot]->saveSettings(nic);
- if (FAILED(rc)) throw rc;
+ /* paranoia check... must not be NULL, but must not crash either. */
+ if (mNetworkAdapters[slot])
+ {
+ rc = mNetworkAdapters[slot]->saveSettings(nic);
+ if (FAILED(rc)) throw rc;
- data.llNetworkAdapters.push_back(nic);
+ data.llNetworkAdapters.push_back(nic);
+ }
}
/* Serial ports */
@@ -9056,24 +9822,27 @@ HRESULT Machine::saveHardware(settings::Hardware &data)
// clipboard
data.clipboardMode = mHWData->mClipboardMode;
+ // drag'n'drop
+ data.dragAndDropMode = mHWData->mDragAndDropMode;
+
/* Guest */
data.ulMemoryBalloonSize = mHWData->mMemoryBalloonSize;
// IO settings
- data.ioSettings.fIoCacheEnabled = !!mHWData->mIoCacheEnabled;
- data.ioSettings.ulIoCacheSize = mHWData->mIoCacheSize;
+ data.ioSettings.fIOCacheEnabled = !!mHWData->mIOCacheEnabled;
+ data.ioSettings.ulIOCacheSize = mHWData->mIOCacheSize;
/* BandwidthControl (required) */
rc = mBandwidthControl->saveSettings(data.ioSettings);
if (FAILED(rc)) throw rc;
/* Host PCI devices */
- for (HWData::PciDeviceAssignmentList::const_iterator it = mHWData->mPciDeviceAssignments.begin();
- it != mHWData->mPciDeviceAssignments.end();
+ for (HWData::PCIDeviceAssignmentList::const_iterator it = mHWData->mPCIDeviceAssignments.begin();
+ it != mHWData->mPCIDeviceAssignments.end();
++it)
{
- ComObjPtr<PciDeviceAttachment> pda = *it;
- settings::HostPciDeviceAttachment hpda;
+ ComObjPtr<PCIDeviceAttachment> pda = *it;
+ settings::HostPCIDeviceAttachment hpda;
rc = pda->saveSettings(hpda);
if (FAILED(rc)) throw rc;
@@ -9114,6 +9883,9 @@ HRESULT Machine::saveHardware(settings::Hardware &data)
/* I presume this doesn't require a backup(). */
mData->mGuestPropertiesModified = FALSE;
#endif /* VBOX_WITH_GUEST_PROPS defined */
+
+ *pDbg = mHWData->mDebugging;
+ *pAutostart = mHWData->mAutostart;
}
catch(std::bad_alloc &)
{
@@ -9162,10 +9934,10 @@ HRESULT Machine::saveStorageControllers(settings::Storage &data)
/* Save IDE emulation settings. */
if (ctl.controllerType == StorageControllerType_IntelAhci)
{
- if ( (FAILED(rc = pCtl->GetIDEEmulationPort(0, (LONG*)&ctl.lIDE0MasterEmulationPort)))
- || (FAILED(rc = pCtl->GetIDEEmulationPort(1, (LONG*)&ctl.lIDE0SlaveEmulationPort)))
- || (FAILED(rc = pCtl->GetIDEEmulationPort(2, (LONG*)&ctl.lIDE1MasterEmulationPort)))
- || (FAILED(rc = pCtl->GetIDEEmulationPort(3, (LONG*)&ctl.lIDE1SlaveEmulationPort)))
+ if ( (FAILED(rc = pCtl->getIDEEmulationPort(0, (LONG*)&ctl.lIDE0MasterEmulationPort)))
+ || (FAILED(rc = pCtl->getIDEEmulationPort(1, (LONG*)&ctl.lIDE0SlaveEmulationPort)))
+ || (FAILED(rc = pCtl->getIDEEmulationPort(2, (LONG*)&ctl.lIDE1MasterEmulationPort)))
+ || (FAILED(rc = pCtl->getIDEEmulationPort(3, (LONG*)&ctl.lIDE1SlaveEmulationPort)))
)
ComAssertComRCRet(rc, rc);
}
@@ -9213,6 +9985,7 @@ HRESULT Machine::saveStorageDevices(ComObjPtr<StorageController> aStorageControl
dev.fPassThrough = pAttach->getPassthrough();
dev.fTempEject = pAttach->getTempEject();
dev.fNonRotational = pAttach->getNonRotational();
+ dev.fDiscard = pAttach->getDiscard();
}
dev.strBwGroup = pAttach->getBandwidthGroup();
@@ -9276,7 +10049,7 @@ HRESULT Machine::saveStateSettings(int aFlags)
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
return rc;
@@ -9285,23 +10058,24 @@ HRESULT Machine::saveStateSettings(int aFlags)
/**
* Ensures that the given medium is added to a media registry. If this machine
* was created with 4.0 or later, then the machine registry is used. Otherwise
- * the global VirtualBox media registry is used. If the medium was actually
- * added to a registry (because it wasn't in the registry yet), the UUID of
- * that registry is added to the given list so that the caller can save the
- * registry.
+ * the global VirtualBox media registry is used.
*
- * Caller must hold machine read lock and at least media tree read lock!
- * Caller must NOT hold any medium locks.
+ * Caller must NOT hold machine lock, media tree or any medium locks!
*
* @param pMedium
- * @param llRegistriesThatNeedSaving
- * @param puuid Optional buffer that receives the registry UUID that was used.
*/
-void Machine::addMediumToRegistry(ComObjPtr<Medium> &pMedium,
- GuidList &llRegistriesThatNeedSaving,
- Guid *puuid)
+void Machine::addMediumToRegistry(ComObjPtr<Medium> &pMedium)
{
- ComObjPtr<Medium> pBase = pMedium->getBase();
+ /* Paranoia checks: do not hold machine or media tree locks. */
+ AssertReturnVoid(!isWriteLockOnCurrentThread());
+ AssertReturnVoid(!mParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
+
+ ComObjPtr<Medium> pBase;
+ {
+ AutoReadLock treeLock(&mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
+ pBase = pMedium->getBase();
+ }
+
/* Paranoia checks: do not hold medium locks. */
AssertReturnVoid(!pMedium->isWriteLockOnCurrentThread());
AssertReturnVoid(!pBase->isWriteLockOnCurrentThread());
@@ -9314,28 +10088,16 @@ void Machine::addMediumToRegistry(ComObjPtr<Medium> &pMedium,
else
uuid = mParent->getGlobalRegistryId(); // VirtualBox global registry UUID
- bool fAdd = false;
if (pMedium->addRegistry(uuid, false /* fRecurse */))
- {
- // registry actually changed:
- VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, uuid);
- fAdd = true;
- }
+ mParent->markRegistryModified(uuid);
/* For more complex hard disk structures it can happen that the base
* medium isn't yet associated with any medium registry. Do that now. */
if (pMedium != pBase)
{
- if ( pBase->addRegistry(uuid, true /* fRecurse */)
- && !fAdd)
- {
- VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, uuid);
- fAdd = true;
- }
+ if (pBase->addRegistry(uuid, true /* fRecurse */))
+ mParent->markRegistryModified(uuid);
}
-
- if (puuid)
- *puuid = uuid;
}
/**
@@ -9363,26 +10125,25 @@ void Machine::addMediumToRegistry(ComObjPtr<Medium> &pMedium,
* many operations left as the number of hard disks
* attached).
* @param aOnline Whether the VM was online prior to this operation.
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs to receive the registry IDs that need saving
*
* @note The progress object is not marked as completed, neither on success nor
* on failure. This is a responsibility of the caller.
*
- * @note Locks this object for writing.
+ * @note Locks this object and the media tree for writing.
*/
HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
ULONG aWeight,
- bool aOnline,
- GuidList *pllRegistriesThatNeedSaving)
+ bool aOnline)
{
LogFlowThisFunc(("aOnline=%d\n", aOnline));
AutoCaller autoCaller(this);
AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AutoMultiWriteLock2 alock(this->lockHandle(),
+ &mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
- /* must be in a protective state because we leave the lock below */
+ /* must be in a protective state because we release the lock below */
AssertReturn( mData->mMachineState == MachineState_Saving
|| mData->mMachineState == MachineState_LiveSnapshotting
|| mData->mMachineState == MachineState_RestoringSnapshot
@@ -9391,6 +10152,7 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
HRESULT rc = S_OK;
+ // use appropriate locked media map (online or offline)
MediumLockListMap lockedMediaOffline;
MediumLockListMap *lockedMediaMap;
if (aOnline)
@@ -9415,10 +10177,12 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
Assert(pMedium);
MediumLockList *pMediumLockList(new MediumLockList());
+ alock.release();
rc = pMedium->createMediumLockList(true /* fFailIfInaccessible */,
false /* fMediumLockWrite */,
NULL,
*pMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
@@ -9434,7 +10198,9 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
}
/* Now lock all media. If this fails, nothing is locked. */
+ alock.release();
rc = lockedMediaMap->Lock();
+ alock.acquire();
if (FAILED(rc))
{
throw setError(rc,
@@ -9503,12 +10269,11 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
rc = diff->init(mParent,
pMedium->getPreferredDiffFormat(),
strFullSnapshotFolder.append(RTPATH_SLASH_STR),
- uuidRegistryParent,
- pllRegistriesThatNeedSaving);
+ uuidRegistryParent);
if (FAILED(rc)) throw rc;
/** @todo r=bird: How is the locking and diff image cleaned up if we fail before
- * the push_back? Looks like we're going to leave medium with the
+ * the push_back? Looks like we're going to release medium with the
* wrong kind of lock (general issue with if we fail anywhere at all)
* and an orphaned VDI in the snapshots folder. */
@@ -9518,25 +10283,32 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
AssertComRCThrowRC(rc);
if (aOnline)
{
+ alock.release();
+ /* The currently attached medium will be read-only, change
+ * the lock type to read. */
rc = pMediumLockList->Update(pMedium, false);
+ alock.acquire();
AssertComRCThrowRC(rc);
}
- /* leave the lock before the potentially lengthy operation */
- alock.leave();
+ /* release the locks before the potentially lengthy operation */
+ alock.release();
rc = pMedium->createDiffStorage(diff, MediumVariant_Standard,
pMediumLockList,
NULL /* aProgress */,
- true /* aWait */,
- pllRegistriesThatNeedSaving);
- alock.enter();
+ true /* aWait */);
+ alock.acquire();
if (FAILED(rc)) throw rc;
rc = lockedMediaMap->Unlock();
AssertComRCThrowRC(rc);
+ alock.release();
rc = pMediumLockList->Append(diff, true);
+ alock.acquire();
AssertComRCThrowRC(rc);
+ alock.release();
rc = lockedMediaMap->Lock();
+ alock.acquire();
AssertComRCThrowRC(rc);
rc = diff->addBackReference(mData->mUuid);
@@ -9555,6 +10327,7 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
false /* aPassthrough */,
false /* aTempEject */,
pAtt->getNonRotational(),
+ pAtt->getDiscard(),
pAtt->getBandwidthGroup());
if (FAILED(rc)) throw rc;
@@ -9565,7 +10338,7 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
}
catch (HRESULT aRC) { rc = aRC; }
- /* unlock all hard disks we locked */
+ /* unlock all hard disks we locked when there is no VM */
if (!aOnline)
{
ErrorInfoKeeper eik;
@@ -9574,13 +10347,6 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
AssertComRC(rc1);
}
- if (FAILED(rc))
- {
- MultiResult mrc = rc;
-
- mrc = deleteImplicitDiffs(pllRegistriesThatNeedSaving);
- }
-
return rc;
}
@@ -9591,102 +10357,201 @@ HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
* Note that to delete hard disks created by #AttachDevice() this method is
* called from #fixupMedia() when the changes are rolled back.
*
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs to receive the registry IDs that need saving
- *
- * @note Locks this object for writing.
+ * @note Locks this object and the media tree for writing.
*/
-HRESULT Machine::deleteImplicitDiffs(GuidList *pllRegistriesThatNeedSaving)
+HRESULT Machine::deleteImplicitDiffs(bool aOnline)
{
+ LogFlowThisFunc(("aOnline=%d\n", aOnline));
+
AutoCaller autoCaller(this);
AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- LogFlowThisFuncEnter();
+ AutoMultiWriteLock2 alock(this->lockHandle(),
+ &mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
+ /* We absolutely must have backed up state. */
AssertReturn(mMediaData.isBackedUp(), E_FAIL);
HRESULT rc = S_OK;
+ MachineState_T oldState = mData->mMachineState;
+
+ /* will release the lock before the potentially lengthy operation,
+ * so protect with the special state (unless already protected) */
+ if ( oldState != MachineState_Saving
+ && oldState != MachineState_LiveSnapshotting
+ && oldState != MachineState_RestoringSnapshot
+ && oldState != MachineState_DeletingSnapshot
+ && oldState != MachineState_DeletingSnapshotOnline
+ && oldState != MachineState_DeletingSnapshotPaused
+ )
+ setMachineState(MachineState_SettingUp);
- MediaData::AttachmentList implicitAtts;
-
- const MediaData::AttachmentList &oldAtts = mMediaData.backedUpData()->mAttachments;
+ // use appropriate locked media map (online or offline)
+ MediumLockListMap lockedMediaOffline;
+ MediumLockListMap *lockedMediaMap;
+ if (aOnline)
+ lockedMediaMap = &mData->mSession.mLockedMedia;
+ else
+ lockedMediaMap = &lockedMediaOffline;
- /* enumerate new attachments */
- for (MediaData::AttachmentList::const_iterator it = mMediaData->mAttachments.begin();
- it != mMediaData->mAttachments.end();
- ++it)
+ try
{
- ComObjPtr<Medium> hd = (*it)->getMedium();
- if (hd.isNull())
- continue;
+ if (!aOnline)
+ {
+ /* lock all attached hard disks early to detect "in use"
+ * situations before deleting actual diffs */
+ for (MediaData::AttachmentList::const_iterator it = mMediaData->mAttachments.begin();
+ it != mMediaData->mAttachments.end();
+ ++it)
+ {
+ MediumAttachment* pAtt = *it;
+ if (pAtt->getType() == DeviceType_HardDisk)
+ {
+ Medium* pMedium = pAtt->getMedium();
+ Assert(pMedium);
+
+ MediumLockList *pMediumLockList(new MediumLockList());
+ alock.release();
+ rc = pMedium->createMediumLockList(true /* fFailIfInaccessible */,
+ false /* fMediumLockWrite */,
+ NULL,
+ *pMediumLockList);
+ alock.acquire();
+
+ if (FAILED(rc))
+ {
+ delete pMediumLockList;
+ throw rc;
+ }
+
+ rc = lockedMediaMap->Insert(pAtt, pMediumLockList);
+ if (FAILED(rc))
+ throw rc;
+ }
+ }
+
+ if (FAILED(rc))
+ throw rc;
+ } // end of offline
+
+ /* Lock lists are now up to date and include implicitly created media */
- if ((*it)->isImplicit())
+ /* Go through remembered attachments and delete all implicitly created
+ * diffs and fix up the attachment information */
+ const MediaData::AttachmentList &oldAtts = mMediaData.backedUpData()->mAttachments;
+ MediaData::AttachmentList implicitAtts;
+ for (MediaData::AttachmentList::const_iterator it = mMediaData->mAttachments.begin();
+ it != mMediaData->mAttachments.end();
+ ++it)
{
- /* deassociate and mark for deletion */
- LogFlowThisFunc(("Detaching '%s', pending deletion\n", (*it)->getLogName()));
- rc = hd->removeBackReference(mData->mUuid);
- AssertComRC(rc);
- implicitAtts.push_back(*it);
- continue;
+ ComObjPtr<MediumAttachment> pAtt = *it;
+ ComObjPtr<Medium> pMedium = pAtt->getMedium();
+ if (pMedium.isNull())
+ continue;
+
+ // Implicit attachments go on the list for deletion and back references are removed.
+ if (pAtt->isImplicit())
+ {
+ /* Deassociate and mark for deletion */
+ LogFlowThisFunc(("Detaching '%s', pending deletion\n", pAtt->getLogName()));
+ rc = pMedium->removeBackReference(mData->mUuid);
+ if (FAILED(rc))
+ throw rc;
+ implicitAtts.push_back(pAtt);
+ continue;
+ }
+
+ /* Was this medium attached before? */
+ if (!findAttachment(oldAtts, pMedium))
+ {
+ /* no: de-associate */
+ LogFlowThisFunc(("Detaching '%s', no deletion\n", pAtt->getLogName()));
+ rc = pMedium->removeBackReference(mData->mUuid);
+ if (FAILED(rc))
+ throw rc;
+ continue;
+ }
+ LogFlowThisFunc(("Not detaching '%s'\n", pAtt->getLogName()));
}
- /* was this hard disk attached before? */
- if (!findAttachment(oldAtts, hd))
+ /* If there are implicit attachments to delete, throw away the lock
+ * map contents (which will unlock all media) since the medium
+ * attachments will be rolled back. Below we need to completely
+ * recreate the lock map anyway since it is infinitely complex to
+ * do this incrementally (would need reconstructing each attachment
+ * change, which would be extremely hairy). */
+ if (implicitAtts.size() != 0)
{
- /* no: de-associate */
- LogFlowThisFunc(("Detaching '%s', no deletion\n", (*it)->getLogName()));
- rc = hd->removeBackReference(mData->mUuid);
- AssertComRC(rc);
- continue;
+ ErrorInfoKeeper eik;
+
+ HRESULT rc1 = lockedMediaMap->Clear();
+ AssertComRC(rc1);
}
- LogFlowThisFunc(("Not detaching '%s'\n", (*it)->getLogName()));
- }
- /* rollback hard disk changes */
- mMediaData.rollback();
+ /* rollback hard disk changes */
+ mMediaData.rollback();
- MultiResult mrc(S_OK);
+ MultiResult mrc(S_OK);
- /* delete unused implicit diffs */
- if (implicitAtts.size() != 0)
- {
- /* will leave the lock before the potentially lengthy
- * operation, so protect with the special state (unless already
- * protected) */
- MachineState_T oldState = mData->mMachineState;
- if ( oldState != MachineState_Saving
- && oldState != MachineState_LiveSnapshotting
- && oldState != MachineState_RestoringSnapshot
- && oldState != MachineState_DeletingSnapshot
- && oldState != MachineState_DeletingSnapshotOnline
- && oldState != MachineState_DeletingSnapshotPaused
- )
- setMachineState(MachineState_SettingUp);
+ // Delete unused implicit diffs.
+ if (implicitAtts.size() != 0)
+ {
+ alock.release();
- alock.leave();
+ for (MediaData::AttachmentList::const_iterator it = implicitAtts.begin();
+ it != implicitAtts.end();
+ ++it)
+ {
+ // Remove medium associated with this attachment.
+ ComObjPtr<MediumAttachment> pAtt = *it;
+ Assert(pAtt);
+ LogFlowThisFunc(("Deleting '%s'\n", pAtt->getLogName()));
+ ComObjPtr<Medium> pMedium = pAtt->getMedium();
+ Assert(pMedium);
+
+ rc = pMedium->deleteStorage(NULL /*aProgress*/, true /*aWait*/);
+ // continue on delete failure, just collect error messages
+ AssertMsg(SUCCEEDED(rc), ("rc=%Rhrc it=%s hd=%s\n", rc, pAtt->getLogName(), pMedium->getLocationFull().c_str() ));
+ mrc = rc;
+ }
- for (MediaData::AttachmentList::const_iterator it = implicitAtts.begin();
- it != implicitAtts.end();
- ++it)
- {
- LogFlowThisFunc(("Deleting '%s'\n", (*it)->getLogName()));
- ComObjPtr<Medium> hd = (*it)->getMedium();
+ alock.acquire();
- rc = hd->deleteStorage(NULL /*aProgress*/, true /*aWait*/,
- pllRegistriesThatNeedSaving);
- AssertMsg(SUCCEEDED(rc), ("rc=%Rhrc it=%s hd=%s\n", rc, (*it)->getLogName(), hd->getLocationFull().c_str() ));
- mrc = rc;
+ /* if there is a VM recreate media lock map as mentioned above,
+ * otherwise it is a waste of time and we leave things unlocked */
+ if (aOnline)
+ {
+ const ComObjPtr<SessionMachine> pMachine = mData->mSession.mMachine;
+ /* must never be NULL, but better safe than sorry */
+ if (!pMachine.isNull())
+ {
+ alock.release();
+ rc = mData->mSession.mMachine->lockMedia();
+ alock.acquire();
+ if (FAILED(rc))
+ throw rc;
+ }
+ }
}
+ }
+ catch (HRESULT aRC) {rc = aRC;}
+
+ if (mData->mMachineState == MachineState_SettingUp)
+ setMachineState(oldState);
- alock.enter();
+ /* unlock all hard disks we locked when there is no VM */
+ if (!aOnline)
+ {
+ ErrorInfoKeeper eik;
- if (mData->mMachineState == MachineState_SettingUp)
- setMachineState(oldState);
+ HRESULT rc1 = lockedMediaMap->Clear();
+ AssertComRC(rc1);
}
- return mrc;
+ return rc;
}
+
/**
* Looks through the given list of media attachments for one with the given parameters
* and returns it, or NULL if not found. The list is a parameter so that backup lists
@@ -9776,13 +10641,11 @@ MediumAttachment* Machine::findAttachment(const MediaData::AttachmentList &ll,
* @param pAttach Medium attachment to detach.
* @param writeLock Machine write lock which the caller must have locked once. This may be released temporarily in here.
* @param pSnapshot If NULL, then the detachment is for the current machine. Otherwise this is for a SnapshotMachine, and this must be its snapshot.
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs to receive the registry IDs that need saving
* @return
*/
HRESULT Machine::detachDevice(MediumAttachment *pAttach,
AutoWriteLock &writeLock,
- Snapshot *pSnapshot,
- GuidList *pllRegistriesThatNeedSaving)
+ Snapshot *pSnapshot)
{
ComObjPtr<Medium> oldmedium = pAttach->getMedium();
DeviceType_T mediumType = pAttach->getType();
@@ -9793,22 +10656,21 @@ HRESULT Machine::detachDevice(MediumAttachment *pAttach,
{
/* attempt to implicitly delete the implicitly created diff */
- /// @todo move the implicit flag from MediumAttachment to Medium
- /// and forbid any hard disk operation when it is implicit. Or maybe
- /// a special media state for it to make it even more simple.
+ /// @todo move the implicit flag from MediumAttachment to Medium
+ /// and forbid any hard disk operation when it is implicit. Or maybe
+ /// a special media state for it to make it even more simple.
Assert(mMediaData.isBackedUp());
- /* will leave the lock before the potentially lengthy operation, so
- * protect with the special state */
+ /* will release the lock before the potentially lengthy operation, so
+ * protect with the special state */
MachineState_T oldState = mData->mMachineState;
setMachineState(MachineState_SettingUp);
writeLock.release();
HRESULT rc = oldmedium->deleteStorage(NULL /*aProgress*/,
- true /*aWait*/,
- pllRegistriesThatNeedSaving);
+ true /*aWait*/);
writeLock.acquire();
@@ -9910,7 +10772,8 @@ HRESULT Machine::detachAllMedia(AutoWriteLock &writeLock,
&& pParent->getType() == MediumType_Normal
&& find(llMedia.begin(), llMedia.end(), pParent) == llMedia.end())
llMedia.push_back(pParent);
- }else
+ }
+ else
break;
pParent = pParent->getParent();
}
@@ -9918,10 +10781,7 @@ HRESULT Machine::detachAllMedia(AutoWriteLock &writeLock,
}
// real machine: then we need to use the proper method
- rc = detachDevice(pAttach,
- writeLock,
- pSnapshot,
- NULL /* pllRegistriesThatNeedSaving */);
+ rc = detachDevice(pAttach, writeLock, pSnapshot);
if (FAILED(rc))
return rc;
@@ -10115,17 +10975,14 @@ void Machine::commitMedia(bool aOnline /*= false*/)
* backed up).
*
* @note Locks this object for writing!
- *
- * @todo r=dj this needs a pllRegistriesThatNeedSaving as well
*/
void Machine::rollbackMedia()
{
AutoCaller autoCaller(this);
- AssertComRCReturnVoid (autoCaller.rc());
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AssertComRCReturnVoid(autoCaller.rc());
- LogFlowThisFunc(("Entering\n"));
+ // AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("Entering rollbackMedia\n"));
HRESULT rc = S_OK;
@@ -10167,9 +11024,7 @@ void Machine::rollbackMedia()
/** @todo convert all this Machine-based voodoo to MediumAttachment
* based rollback logic. */
- // @todo r=dj the below totally fails if this gets called from Machine::rollback(),
- // which gets called if Machine::registeredInit() fails...
- deleteImplicitDiffs(NULL /* pllRegistriesThatNeedSaving */);
+ deleteImplicitDiffs(Global::IsOnline(mData->mMachineState));
return;
}
@@ -10195,6 +11050,9 @@ bool Machine::isInOwnDir(Utf8Str *aSettingsDir /* = NULL */) const
Utf8Str strConfigFileOnly(mData->m_strConfigFileFull); // path/to/machinesfolder/vmname/vmname.vbox
strConfigFileOnly.stripPath() // vmname.vbox
.stripExt(); // vmname
+ /** @todo hack, make somehow use of ComposeMachineFilename */
+ if (mUserData->s.fDirectoryIncludesUUID)
+ strConfigFileOnly += Utf8StrFmt(" (%RTuuid)", mData->mUuid.raw());
AssertReturn(!strMachineDirName.isEmpty(), false);
AssertReturn(!strConfigFileOnly.isEmpty(), false);
@@ -10272,12 +11130,14 @@ void Machine::rollback(bool aNotify)
if (mBandwidthControl && (mData->flModifications & IsModified_BandwidthControl))
mBandwidthControl->rollback();
- ComPtr<INetworkAdapter> networkAdapters[RT_ELEMENTS(mNetworkAdapters)];
+ if (!mHWData.isNull())
+ mNetworkAdapters.resize(Global::getMaxNetworkAdapters(mHWData->mChipsetType));
+ NetworkAdapterVector networkAdapters(mNetworkAdapters.size());
ComPtr<ISerialPort> serialPorts[RT_ELEMENTS(mSerialPorts)];
ComPtr<IParallelPort> parallelPorts[RT_ELEMENTS(mParallelPorts)];
if (mData->flModifications & IsModified_NetworkAdapters)
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); slot++)
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
if ( mNetworkAdapters[slot]
&& mNetworkAdapters[slot]->isModified())
{
@@ -10309,7 +11169,7 @@ void Machine::rollback(bool aNotify)
ComObjPtr<Machine> that = this;
uint32_t flModifications = mData->flModifications;
- alock.leave();
+ alock.release();
if (flModifications & IsModified_SharedFolders)
that->onSharedFolderChange();
@@ -10319,13 +11179,13 @@ void Machine::rollback(bool aNotify)
if (flModifications & IsModified_USB)
that->onUSBControllerChange();
- for (ULONG slot = 0; slot < RT_ELEMENTS(networkAdapters); slot ++)
+ for (ULONG slot = 0; slot < networkAdapters.size(); slot++)
if (networkAdapters[slot])
that->onNetworkAdapterChange(networkAdapters[slot], FALSE);
- for (ULONG slot = 0; slot < RT_ELEMENTS(serialPorts); slot ++)
+ for (ULONG slot = 0; slot < RT_ELEMENTS(serialPorts); slot++)
if (serialPorts[slot])
that->onSerialPortChange(serialPorts[slot]);
- for (ULONG slot = 0; slot < RT_ELEMENTS(parallelPorts); slot ++)
+ for (ULONG slot = 0; slot < RT_ELEMENTS(parallelPorts); slot++)
if (parallelPorts[slot])
that->onParallelPortChange(parallelPorts[slot]);
@@ -10373,8 +11233,57 @@ void Machine::commit()
mUSBController->commit();
mBandwidthControl->commit();
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); slot++)
- mNetworkAdapters[slot]->commit();
+ /* Since mNetworkAdapters is a list which might have been changed (resized)
+ * without using the Backupable<> template we need to handle the copying
+ * of the list entries manually, including the creation of peers for the
+ * new objects. */
+ bool commitNetworkAdapters = false;
+ size_t newSize = Global::getMaxNetworkAdapters(mHWData->mChipsetType);
+ if (mPeer)
+ {
+ /* commit everything, even the ones which will go away */
+ for (size_t slot = 0; slot < mNetworkAdapters.size(); slot++)
+ mNetworkAdapters[slot]->commit();
+ /* copy over the new entries, creating a peer and uninit the original */
+ mPeer->mNetworkAdapters.resize(RT_MAX(newSize, mPeer->mNetworkAdapters.size()));
+ for (size_t slot = 0; slot < newSize; slot++)
+ {
+ /* look if this adapter has a peer device */
+ ComObjPtr<NetworkAdapter> peer = mNetworkAdapters[slot]->getPeer();
+ if (!peer)
+ {
+ /* no peer means the adapter is a newly created one;
+ * create a peer owning data this data share it with */
+ peer.createObject();
+ peer->init(mPeer, mNetworkAdapters[slot], true /* aReshare */);
+ }
+ mPeer->mNetworkAdapters[slot] = peer;
+ }
+ /* uninit any no longer needed network adapters */
+ for (size_t slot = newSize; slot < mNetworkAdapters.size(); slot++)
+ mNetworkAdapters[slot]->uninit();
+ for (size_t slot = newSize; slot < mPeer->mNetworkAdapters.size(); slot++)
+ {
+ if (mPeer->mNetworkAdapters[slot])
+ mPeer->mNetworkAdapters[slot]->uninit();
+ }
+ /* Keep the original network adapter count until this point, so that
+ * discarding a chipset type change will not lose settings. */
+ mNetworkAdapters.resize(newSize);
+ mPeer->mNetworkAdapters.resize(newSize);
+ }
+ else
+ {
+ /* we have no peer (our parent is the newly created machine);
+ * just commit changes to the network adapters */
+ commitNetworkAdapters = true;
+ }
+ if (commitNetworkAdapters)
+ {
+ for (size_t slot = 0; slot < mNetworkAdapters.size(); slot++)
+ mNetworkAdapters[slot]->commit();
+ }
+
for (ULONG slot = 0; slot < RT_ELEMENTS(mSerialPorts); slot++)
mSerialPorts[slot]->commit();
for (ULONG slot = 0; slot < RT_ELEMENTS(mParallelPorts); slot++)
@@ -10388,8 +11297,6 @@ void Machine::commit()
if (mPeer)
{
- AutoWriteLock peerlock(mPeer COMMA_LOCKVAL_SRC_POS);
-
/* Commit all changes to new controllers (this will reshare data with
* peers for those who have peers) */
StorageControllerList *newList = new StorageControllerList();
@@ -10517,7 +11424,8 @@ void Machine::copyFrom(Machine *aThat)
mStorageControllers->push_back(ctrl);
}
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); slot++)
+ mNetworkAdapters.resize(aThat->mNetworkAdapters.size());
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
mNetworkAdapters[slot]->copyFrom(aThat->mNetworkAdapters[slot]);
for (ULONG slot = 0; slot < RT_ELEMENTS(mSerialPorts); slot++)
mSerialPorts[slot]->copyFrom(aThat->mSerialPorts[slot]);
@@ -10552,6 +11460,26 @@ bool Machine::isControllerHotplugCapable(StorageControllerType_T enmCtrlType)
#ifdef VBOX_WITH_RESOURCE_USAGE_API
+void Machine::getDiskList(MediaList &list)
+{
+ for (MediaData::AttachmentList::const_iterator it = mMediaData->mAttachments.begin();
+ it != mMediaData->mAttachments.end();
+ ++it)
+ {
+ MediumAttachment* pAttach = *it;
+ /* just in case */
+ AssertStmt(pAttach, continue);
+
+ AutoCaller localAutoCallerA(pAttach);
+ if (FAILED(localAutoCallerA.rc())) continue;
+
+ AutoReadLock local_alockA(pAttach COMMA_LOCKVAL_SRC_POS);
+
+ if (pAttach->getType() == DeviceType_HardDisk)
+ list.push_back(pAttach->getMedium());
+ }
+}
+
void Machine::registerMetrics(PerformanceCollector *aCollector, Machine *aMachine, RTPROCESS pid)
{
AssertReturnVoid(isWriteLockOnCurrentThread());
@@ -10565,6 +11493,12 @@ void Machine::registerMetrics(PerformanceCollector *aCollector, Machine *aMachin
"Percentage of processor time spent in kernel mode by the VM process.");
pm::SubMetric *ramUsageUsed = new pm::SubMetric("RAM/Usage/Used",
"Size of resident portion of VM process in memory.");
+ pm::SubMetric *diskUsageUsed = new pm::SubMetric("Disk/Usage/Used",
+ "Actual size of all VM disks combined.");
+ pm::SubMetric *machineNetRx = new pm::SubMetric("Net/Rate/Rx",
+ "Network receive rate.");
+ pm::SubMetric *machineNetTx = new pm::SubMetric("Net/Rate/Tx",
+ "Network transmit rate.");
/* Create and register base metrics */
pm::BaseMetric *cpuLoad = new pm::MachineCpuLoadRaw(hal, aMachine, pid,
cpuLoadUser, cpuLoadKernel);
@@ -10572,6 +11506,11 @@ void Machine::registerMetrics(PerformanceCollector *aCollector, Machine *aMachin
pm::BaseMetric *ramUsage = new pm::MachineRamUsage(hal, aMachine, pid,
ramUsageUsed);
aCollector->registerBaseMetric(ramUsage);
+ MediaList disks;
+ getDiskList(disks);
+ pm::BaseMetric *diskUsage = new pm::MachineDiskUsage(hal, aMachine, disks,
+ diskUsageUsed);
+ aCollector->registerBaseMetric(diskUsage);
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser, 0));
aCollector->registerMetric(new pm::Metric(cpuLoad, cpuLoadUser,
@@ -10596,6 +11535,14 @@ void Machine::registerMetrics(PerformanceCollector *aCollector, Machine *aMachin
aCollector->registerMetric(new pm::Metric(ramUsage, ramUsageUsed,
new pm::AggregateMax()));
+ aCollector->registerMetric(new pm::Metric(diskUsage, diskUsageUsed, 0));
+ aCollector->registerMetric(new pm::Metric(diskUsage, diskUsageUsed,
+ new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(diskUsage, diskUsageUsed,
+ new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(diskUsage, diskUsageUsed,
+ new pm::AggregateMax()));
+
/* Guest metrics collector */
mCollectorGuest = new pm::CollectorGuest(aMachine, pid);
@@ -10621,6 +11568,10 @@ void Machine::registerMetrics(PerformanceCollector *aCollector, Machine *aMachin
pm::SubMetric *guestPagedTotal = new pm::SubMetric("Guest/Pagefile/Usage/Total", "Total amount of space in the page file.");
/* Create and register base metrics */
+ pm::BaseMetric *machineNetRate = new pm::MachineNetRate(mCollectorGuest, aMachine,
+ machineNetRx, machineNetTx);
+ aCollector->registerBaseMetric(machineNetRate);
+
pm::BaseMetric *guestCpuLoad = new pm::GuestCpuLoad(mCollectorGuest, aMachine,
guestLoadUser, guestLoadKernel, guestLoadIdle);
aCollector->registerBaseMetric(guestCpuLoad);
@@ -10631,6 +11582,16 @@ void Machine::registerMetrics(PerformanceCollector *aCollector, Machine *aMachin
guestMemCache, guestPagedTotal);
aCollector->registerBaseMetric(guestCpuMem);
+ aCollector->registerMetric(new pm::Metric(machineNetRate, machineNetRx, 0));
+ aCollector->registerMetric(new pm::Metric(machineNetRate, machineNetRx, new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(machineNetRate, machineNetRx, new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(machineNetRate, machineNetRx, new pm::AggregateMax()));
+
+ aCollector->registerMetric(new pm::Metric(machineNetRate, machineNetTx, 0));
+ aCollector->registerMetric(new pm::Metric(machineNetRate, machineNetTx, new pm::AggregateAvg()));
+ aCollector->registerMetric(new pm::Metric(machineNetRate, machineNetTx, new pm::AggregateMin()));
+ aCollector->registerMetric(new pm::Metric(machineNetRate, machineNetTx, new pm::AggregateMax()));
+
aCollector->registerMetric(new pm::Metric(guestCpuLoad, guestLoadUser, 0));
aCollector->registerMetric(new pm::Metric(guestCpuLoad, guestLoadUser, new pm::AggregateAvg()));
aCollector->registerMetric(new pm::Metric(guestCpuLoad, guestLoadUser, new pm::AggregateMin()));
@@ -10877,7 +11838,8 @@ HRESULT SessionMachine::init(Machine *aMachine)
mUSBController->init(this, aMachine->mUSBController);
/* create a list of network adapters that will be mutable */
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); slot++)
+ mNetworkAdapters.resize(aMachine->mNetworkAdapters.size());
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
{
unconst(mNetworkAdapters[slot]).createObject();
mNetworkAdapters[slot]->init(this, aMachine->mNetworkAdapters[slot]);
@@ -11008,7 +11970,7 @@ void SessionMachine::uninit(Uninit::Reason aReason)
*/
unregisterMetrics(mParent->performanceCollector(), mPeer);
#endif
- /* The guest must be unregistered after its metrics (#5949). */
+ /* The guest must be unregistered after its metrics (@bugref{5949}). */
LogAleksey(("{%p} " LOG_FN_FMT ": mCollectorGuest=%p\n",
this, __PRETTY_FUNCTION__, mCollectorGuest));
if (mCollectorGuest)
@@ -11064,11 +12026,11 @@ void SessionMachine::uninit(Uninit::Reason aReason)
* Machine::LaunchVMProcess(), therefore it is our child. We
* need to queue the PID to reap the process (and avoid zombies on
* Linux). */
- Assert(mData->mSession.mPid != NIL_RTPROCESS);
- mParent->addProcessToReap(mData->mSession.mPid);
+ Assert(mData->mSession.mPID != NIL_RTPROCESS);
+ mParent->addProcessToReap(mData->mSession.mPID);
}
- mData->mSession.mPid = NIL_RTPROCESS;
+ mData->mSession.mPID = NIL_RTPROCESS;
if (aReason == Uninit::Unexpected)
{
@@ -11173,13 +12135,8 @@ void SessionMachine::uninit(Uninit::Reason aReason)
/* free the essential data structure last */
mData.free();
-#if 1 /** @todo Please review this change! (bird) */
- /* drop the exclusive lock before setting the below two to NULL */
+ /* release the exclusive lock before setting the below two to NULL */
multilock.release();
-#else
- /* leave the exclusive lock before setting the below two to NULL */
- multilock.leave();
-#endif
unconst(mParent) = NULL;
unconst(mPeer) = NULL;
@@ -11206,19 +12163,20 @@ RWLockHandle *SessionMachine::lockHandle() const
/**
* Passes collected guest statistics to performance collector object
*/
-STDMETHODIMP SessionMachine::ReportGuestStatistics(ULONG aValidStats, ULONG aCpuUser,
- ULONG aCpuKernel, ULONG aCpuIdle,
- ULONG aMemTotal, ULONG aMemFree,
- ULONG aMemBalloon, ULONG aMemShared,
- ULONG aMemCache, ULONG aPageTotal,
- ULONG aAllocVMM, ULONG aFreeVMM,
- ULONG aBalloonedVMM, ULONG aSharedVMM)
+STDMETHODIMP SessionMachine::ReportVmStatistics(ULONG aValidStats, ULONG aCpuUser,
+ ULONG aCpuKernel, ULONG aCpuIdle,
+ ULONG aMemTotal, ULONG aMemFree,
+ ULONG aMemBalloon, ULONG aMemShared,
+ ULONG aMemCache, ULONG aPageTotal,
+ ULONG aAllocVMM, ULONG aFreeVMM,
+ ULONG aBalloonedVMM, ULONG aSharedVMM,
+ ULONG aVmNetRx, ULONG aVmNetTx)
{
if (mCollectorGuest)
mCollectorGuest->updateStats(aValidStats, aCpuUser, aCpuKernel, aCpuIdle,
aMemTotal, aMemFree, aMemBalloon, aMemShared,
aMemCache, aPageTotal, aAllocVMM, aFreeVMM,
- aBalloonedVMM, aSharedVMM);
+ aBalloonedVMM, aSharedVMM, aVmNetRx, aVmNetTx);
return S_OK;
}
@@ -11319,7 +12277,7 @@ STDMETHODIMP SessionMachine::EndPowerUp(LONG iResult)
* now to offer the performance metrics for a running machine
* object. Doing it earlier wouldn't be safe. */
registerMetrics(mParent->performanceCollector(), mPeer,
- mData->mSession.mPid);
+ mData->mSession.mPID);
#endif /* VBOX_WITH_RESOURCE_USAGE_API */
}
@@ -11575,7 +12533,7 @@ STDMETHODIMP SessionMachine::OnSessionEnd(ISession *aSession,
/* Creating a Progress object requires the VirtualBox lock, and
* thus locking it here is required by the lock order rules. */
- AutoMultiWriteLock2 alock(mParent->lockHandle(), this->lockHandle() COMMA_LOCKVAL_SRC_POS);
+ AutoMultiWriteLock2 alock(mParent, this COMMA_LOCKVAL_SRC_POS);
if (control == mData->mSession.mDirectControl)
{
@@ -11638,6 +12596,9 @@ STDMETHODIMP SessionMachine::OnSessionEnd(ISession *aSession,
mData->mSession.mRemoteControls.erase(it);
}
+ /* signal the client watcher thread, because the client is going away */
+ mParent->updateClientWatcher();
+
LogFlowThisFuncLeave();
return S_OK;
}
@@ -11770,10 +12731,10 @@ STDMETHODIMP SessionMachine::PullGuestProperties(ComSafeArrayOut(BSTR, aNames),
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- AssertReturn(!ComSafeArrayOutIsNull(aNames), E_POINTER);
- AssertReturn(!ComSafeArrayOutIsNull(aValues), E_POINTER);
- AssertReturn(!ComSafeArrayOutIsNull(aTimestamps), E_POINTER);
- AssertReturn(!ComSafeArrayOutIsNull(aFlags), E_POINTER);
+ CheckComArgOutSafeArrayPointerValid(aNames);
+ CheckComArgOutSafeArrayPointerValid(aValues);
+ CheckComArgOutSafeArrayPointerValid(aTimestamps);
+ CheckComArgOutSafeArrayPointerValid(aFlags);
size_t cEntries = mHWData->mGuestProperties.size();
com::SafeArray<BSTR> names(cEntries);
@@ -11905,7 +12866,7 @@ STDMETHODIMP SessionMachine::PushGuestProperty(IN_BSTR aName,
RTSTR_MAX, NULL)
)
{
- alock.leave();
+ alock.release();
mParent->onGuestPropertyChange(mData->mUuid,
aName,
@@ -11915,7 +12876,7 @@ STDMETHODIMP SessionMachine::PushGuestProperty(IN_BSTR aName,
}
catch (...)
{
- return VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ return VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
return S_OK;
#else
@@ -11923,6 +12884,29 @@ STDMETHODIMP SessionMachine::PushGuestProperty(IN_BSTR aName,
#endif
}
+STDMETHODIMP SessionMachine::LockMedia()
+{
+ AutoCaller autoCaller(this);
+ AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+ AutoMultiWriteLock2 alock(this->lockHandle(),
+ &mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
+
+ AssertReturn( mData->mMachineState == MachineState_Starting
+ || mData->mMachineState == MachineState_Restoring
+ || mData->mMachineState == MachineState_TeleportingIn, E_FAIL);
+
+ clearError();
+ alock.release();
+ return lockMedia();
+}
+
+STDMETHODIMP SessionMachine::UnlockMedia()
+{
+ unlockMedia();
+ return S_OK;
+}
+
STDMETHODIMP SessionMachine::EjectMedium(IMediumAttachment *aAttachment,
IMediumAttachment **aNewAttachment)
{
@@ -12138,7 +13122,7 @@ HRESULT SessionMachine::onNATRedirectRuleChange(ULONG ulSlot, BOOL aNatRuleRemov
* instead acting like callback we ask IVirtualBox deliver corresponding event
*/
- mParent->onNatRedirectChange(getId(), ulSlot, RT_BOOL(aNatRuleRemove), aRuleName, aProto, aHostIp, aHostPort, aGuestIp, aGuestPort);
+ mParent->onNatRedirectChange(getId(), ulSlot, RT_BOOL(aNatRuleRemove), aRuleName, aProto, aHostIp, (uint16_t)aHostPort, aGuestIp, (uint16_t)aGuestPort);
return S_OK;
}
@@ -12242,7 +13226,7 @@ HRESULT SessionMachine::onCPUChange(ULONG aCPU, BOOL aRemove)
LogFlowThisFunc(("\n"));
AutoCaller autoCaller(this);
- AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
+ AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
ComPtr<IInternalSessionControl> directControl;
{
@@ -12262,7 +13246,7 @@ HRESULT SessionMachine::onCPUExecutionCapChange(ULONG aExecutionCap)
LogFlowThisFunc(("\n"));
AutoCaller autoCaller(this);
- AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
+ AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
ComPtr<IInternalSessionControl> directControl;
{
@@ -12347,6 +13331,52 @@ HRESULT SessionMachine::onSharedFolderChange()
}
/**
+ * @note Locks this object for reading.
+ */
+HRESULT SessionMachine::onClipboardModeChange(ClipboardMode_T aClipboardMode)
+{
+ LogFlowThisFunc(("\n"));
+
+ AutoCaller autoCaller(this);
+ AssertComRCReturnRC(autoCaller.rc());
+
+ ComPtr<IInternalSessionControl> directControl;
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ directControl = mData->mSession.mDirectControl;
+ }
+
+ /* ignore notifications sent after #OnSessionEnd() is called */
+ if (!directControl)
+ return S_OK;
+
+ return directControl->OnClipboardModeChange(aClipboardMode);
+}
+
+/**
+ * @note Locks this object for reading.
+ */
+HRESULT SessionMachine::onDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode)
+{
+ LogFlowThisFunc(("\n"));
+
+ AutoCaller autoCaller(this);
+ AssertComRCReturnRC(autoCaller.rc());
+
+ ComPtr<IInternalSessionControl> directControl;
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ directControl = mData->mSession.mDirectControl;
+ }
+
+ /* ignore notifications sent after #OnSessionEnd() is called */
+ if (!directControl)
+ return S_OK;
+
+ return directControl->OnDragAndDropModeChange(aDragAndDropMode);
+}
+
+/**
* @note Locks this object for reading.
*/
HRESULT SessionMachine::onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup)
@@ -12354,7 +13384,7 @@ HRESULT SessionMachine::onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup)
LogFlowThisFunc(("\n"));
AutoCaller autoCaller(this);
- AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
+ AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
ComPtr<IInternalSessionControl> directControl;
{
@@ -12396,7 +13426,7 @@ HRESULT SessionMachine::onStorageDeviceChange(IMediumAttachment *aAttachment, BO
* Returns @c true if this machine's USB controller reports it has a matching
* filter for the given USB device and @c false otherwise.
*
- * @note Caller must have requested machine read lock.
+ * @note locks this object for reading.
*/
bool SessionMachine::hasMatchingUSBFilter(const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs)
{
@@ -12406,8 +13436,9 @@ bool SessionMachine::hasMatchingUSBFilter(const ComObjPtr<HostUSBDevice> &aDevic
if (!autoCaller.isOk())
return false;
-
#ifdef VBOX_WITH_USB
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
switch (mData->mMachineState)
{
case MachineState_Starting:
@@ -12417,6 +13448,7 @@ bool SessionMachine::hasMatchingUSBFilter(const ComObjPtr<HostUSBDevice> &aDevic
case MachineState_Running:
/** @todo Live Migration: snapshoting & teleporting. Need to fend things of
* elsewhere... */
+ alock.release();
return mUSBController->hasMatchingFilter(aDevice, aMaskedIfs);
default: break;
}
@@ -12598,8 +13630,7 @@ void SessionMachine::releaseSavedStateFile(const Utf8Str &strStateFile,
* locked as described above; on failure no media is locked at all (all
* succeeded individual locks will be undone).
*
- * This method is intended to be called when the machine is in Starting or
- * Restoring state and asserts otherwise.
+ * The caller is responsible for doing the necessary state sanity checks.
*
* The locks made by this method must be undone by calling #unlockMedia() when
* no more needed.
@@ -12609,15 +13640,12 @@ HRESULT SessionMachine::lockMedia()
AutoCaller autoCaller(this);
AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AutoMultiWriteLock2 alock(this->lockHandle(),
+ &mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
- AssertReturn( mData->mMachineState == MachineState_Starting
- || mData->mMachineState == MachineState_Restoring
- || mData->mMachineState == MachineState_TeleportingIn, E_FAIL);
/* bail out if trying to lock things with already set up locking */
AssertReturn(mData->mSession.mLockedMedia.IsEmpty(), E_FAIL);
- clearError();
MultiResult mrc(S_OK);
/* Collect locking information for all medium objects attached to the VM. */
@@ -12641,10 +13669,12 @@ HRESULT SessionMachine::lockMedia()
|| mediumType == MediumType_Shareable;
bool fIsVitalImage = (devType == DeviceType_HardDisk);
+ alock.release();
mrc = pMedium->createMediumLockList(fIsVitalImage /* fFailIfInaccessible */,
!fIsReadOnlyLock /* fMediumLockWrite */,
NULL,
*pMediumLockList);
+ alock.acquire();
if (FAILED(mrc))
{
delete pMediumLockList;
@@ -12666,7 +13696,9 @@ HRESULT SessionMachine::lockMedia()
if (SUCCEEDED(mrc))
{
/* Now lock all media. If this fails, nothing is locked. */
+ alock.release();
HRESULT rc = mData->mSession.mLockedMedia.Lock();
+ alock.acquire();
if (FAILED(rc))
{
mrc = setError(rc,
@@ -12699,6 +13731,10 @@ void SessionMachine::unlockMedia()
* Helper to change the machine state (reimplementation).
*
* @note Locks this object for writing.
+ * @note This method must not call saveSettings or SaveSettings, otherwise
+ * it can cause crashes in random places due to unexpectedly committing
+ * the current settings. The caller is responsible for that. The call
+ * to saveStateSettings is fine, because this method does not commit.
*/
HRESULT SessionMachine::setMachineState(MachineState_T aMachineState)
{
@@ -12897,7 +13933,6 @@ HRESULT SessionMachine::setMachineState(MachineState_T aMachineState)
{
mData->mCurrentStateModified = TRUE;
stsFlags |= SaveSTS_CurStateModified;
- SaveSettings(); // @todo r=dj why the public method? why first SaveSettings and then saveStateSettings?
}
}
#endif
diff --git a/src/VBox/Main/src-server/MachineImplCloneVM.cpp b/src/VBox/Main/src-server/MachineImplCloneVM.cpp
index fccf4cfc3..d010a04f6 100644
--- a/src/VBox/Main/src-server/MachineImplCloneVM.cpp
+++ b/src/VBox/Main/src-server/MachineImplCloneVM.cpp
@@ -114,7 +114,7 @@ struct MachineCloneVMPrivate
void updateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
void updateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
void updateStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const;
- HRESULT createDifferencingMedium(const ComObjPtr<Medium> &pParent, const Utf8Str &strSnapshotFolder, RTCList<ComObjPtr<Medium> > &newMedia, ComObjPtr<Medium> *ppDiff) const;
+ HRESULT createDifferencingMedium(const ComObjPtr<Machine> &pMachine, const ComObjPtr<Medium> &pParent, const Utf8Str &strSnapshotFolder, RTCList<ComObjPtr<Medium> > &newMedia, ComObjPtr<Medium> *ppDiff) const;
static int copyStateFileProgress(unsigned uPercentage, void *pvUser);
/* Private q and parent pointer */
@@ -643,22 +643,26 @@ void MachineCloneVMPrivate::updateStateFile(settings::SnapshotsList &snl, const
}
}
-HRESULT MachineCloneVMPrivate::createDifferencingMedium(const ComObjPtr<Medium> &pParent, const Utf8Str &strSnapshotFolder, RTCList<ComObjPtr<Medium> > &newMedia, ComObjPtr<Medium> *ppDiff) const
+HRESULT MachineCloneVMPrivate::createDifferencingMedium(const ComObjPtr<Machine> &pMachine, const ComObjPtr<Medium> &pParent, const Utf8Str &strSnapshotFolder, RTCList<ComObjPtr<Medium> > &newMedia, ComObjPtr<Medium> *ppDiff) const
{
HRESULT rc = S_OK;
try
{
- Bstr bstrSrcId;
- rc = pParent->COMGETTER(Id)(bstrSrcId.asOutParam());
- if (FAILED(rc)) throw rc;
+ // check validity of parent object
+ {
+ AutoReadLock alock(pParent COMMA_LOCKVAL_SRC_POS);
+ Bstr bstrSrcId;
+ rc = pParent->COMGETTER(Id)(bstrSrcId.asOutParam());
+ if (FAILED(rc)) throw rc;
+ }
ComObjPtr<Medium> diff;
diff.createObject();
rc = diff->init(p->getVirtualBox(),
pParent->getPreferredDiffFormat(),
Utf8StrFmt("%s%c", strSnapshotFolder.c_str(), RTPATH_DELIMITER),
- Guid::Empty, /* empty media registry */
- NULL); /* pllRegistriesThatNeedSaving */
+ Guid::Empty /* empty media registry */);
if (FAILED(rc)) throw rc;
+
MediumLockList *pMediumLockList(new MediumLockList());
rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
@@ -667,12 +671,12 @@ HRESULT MachineCloneVMPrivate::createDifferencingMedium(const ComObjPtr<Medium>
if (FAILED(rc)) throw rc;
rc = pMediumLockList->Lock();
if (FAILED(rc)) throw rc;
+
/* this already registers the new diff image */
rc = pParent->createDiffStorage(diff, MediumVariant_Standard,
pMediumLockList,
NULL /* aProgress */,
- true /* aWait */,
- NULL); // pllRegistriesThatNeedSaving
+ true /* aWait */);
delete pMediumLockList;
if (FAILED(rc)) throw rc;
/* Remember created medium. */
@@ -685,7 +689,7 @@ HRESULT MachineCloneVMPrivate::createDifferencingMedium(const ComObjPtr<Medium>
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(pMachine, RT_SRC_POS);
}
return rc;
@@ -732,7 +736,7 @@ HRESULT MachineCloneVM::start(IProgress **pProgress)
/** @todo r=klaus this code cannot deal with someone crazy specifying
* IMachine corresponding to a mutable machine as d->pSrcMachine */
if (d->pSrcMachine->isSessionMachine())
- throw E_FAIL;
+ throw p->setError(E_INVALIDARG, "The source machine is mutable");
/* Handle the special case that someone is requesting a _full_ clone
* with all snapshots (and the current state), but uses a snapshot
@@ -749,7 +753,6 @@ HRESULT MachineCloneVM::start(IProgress **pProgress)
if (FAILED(rc)) throw rc;
d->pSrcMachine = (Machine*)(IMachine*)newSrcMachine;
}
-
bool fSubtreeIncludesCurrent = false;
ComObjPtr<Machine> pCurrState;
if (d->mode == CloneMode_MachineAndChildStates)
@@ -764,18 +767,18 @@ HRESULT MachineCloneVM::start(IProgress **pProgress)
rc = d->pSrcMachine->getVirtualBox()->FindMachine(bstrSrcMachineId.raw(), pCurr.asOutParam());
if (FAILED(rc)) throw rc;
if (pCurr.isNull())
- throw E_FAIL;
+ throw p->setError(VBOX_E_OBJECT_NOT_FOUND);
pCurrState = (Machine *)(IMachine *)pCurr;
ComPtr<ISnapshot> pSnapshot;
rc = pCurrState->COMGETTER(CurrentSnapshot)(pSnapshot.asOutParam());
if (FAILED(rc)) throw rc;
if (pSnapshot.isNull())
- throw E_FAIL;
+ throw p->setError(VBOX_E_OBJECT_NOT_FOUND);
ComPtr<IMachine> pCurrSnapMachine;
rc = pSnapshot->COMGETTER(Machine)(pCurrSnapMachine.asOutParam());
if (FAILED(rc)) throw rc;
if (pCurrSnapMachine.isNull())
- throw E_FAIL;
+ throw p->setError(VBOX_E_OBJECT_NOT_FOUND);
/* now check if there is a parent chain which leads to the
* snapshot machine defining the subtree. */
@@ -785,7 +788,7 @@ HRESULT MachineCloneVM::start(IProgress **pProgress)
rc = pSnapshot->COMGETTER(Machine)(pSnapMachine.asOutParam());
if (FAILED(rc)) throw rc;
if (pSnapMachine.isNull())
- throw E_FAIL;
+ throw p->setError(VBOX_E_OBJECT_NOT_FOUND);
if (pSnapMachine == d->pSrcMachine)
{
fSubtreeIncludesCurrent = true;
@@ -839,7 +842,7 @@ HRESULT MachineCloneVM::start(IProgress **pProgress)
if (fSubtreeIncludesCurrent)
{
if (pCurrState.isNull())
- throw E_FAIL;
+ throw p->setError(VBOX_E_OBJECT_NOT_FOUND);
machineList.append(pCurrState);
}
else
@@ -1019,7 +1022,6 @@ HRESULT MachineCloneVM::run()
typedef std::map<Utf8Str, ComObjPtr<Medium> > TStrMediumMap;
typedef std::pair<Utf8Str, ComObjPtr<Medium> > TStrMediumPair;
TStrMediumMap map;
- GuidList llRegistriesThatNeedSaving;
size_t cDisks = 0;
for (size_t i = 0; i < d->llMedias.size(); ++i)
{
@@ -1048,14 +1050,18 @@ HRESULT MachineCloneVM::run()
IMedium *pTmp = pMedium;
ComObjPtr<Medium> pLMedium = static_cast<Medium*>(pTmp);
if (pLMedium.isNull())
- throw E_POINTER;
+ throw p->setError(VBOX_E_OBJECT_NOT_FOUND);
ComObjPtr<Medium> pBase = pLMedium->getBase();
if (pBase->isReadOnly())
{
ComObjPtr<Medium> pDiff;
/* create the diff under the snapshot medium */
- rc = d->createDifferencingMedium(pLMedium, strTrgSnapshotFolder,
+ trgLock.release();
+ srcLock.release();
+ rc = d->createDifferencingMedium(p, pLMedium, strTrgSnapshotFolder,
newMedia, &pDiff);
+ srcLock.acquire();
+ trgLock.acquire();
if (FAILED(rc)) throw rc;
map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pDiff));
/* diff image has to be used... */
@@ -1149,8 +1155,7 @@ HRESULT MachineCloneVM::run()
rc = pTarget->init(p->mParent,
Utf8Str(bstrSrcFormat),
strFile,
- Guid::Empty, /* empty media registry */
- NULL /* llRegistriesThatNeedSaving */);
+ Guid::Empty /* empty media registry */);
if (FAILED(rc)) throw rc;
/* Update the new uuid. */
@@ -1178,13 +1183,10 @@ HRESULT MachineCloneVM::run()
LONG iRc;
rc = progress2->COMGETTER(ResultCode)(&iRc);
if (FAILED(rc)) throw rc;
+ /* If the thread of the progress object has an error, then
+ * retrieve the error info from there, or it'll be lost. */
if (FAILED(iRc))
- {
- /* If the thread of the progress object has an error, then
- * retrieve the error info from there, or it'll be lost. */
- ProgressErrorInfo info(progress2);
- throw p->setError(iRc, Utf8Str(info.getText()).c_str());
- }
+ throw p->setError(ProgressErrorInfo(progress2));
/* Remember created medium. */
newMedia.append(pTarget);
/* Get the medium type from the source and set it to the
@@ -1198,7 +1200,8 @@ HRESULT MachineCloneVM::run()
/* register the new harddisk */
{
AutoWriteLock tlock(p->mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
- rc = p->mParent->registerMedium(pTarget, &pTarget, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */);
+ rc = p->mParent->registerMedium(pTarget, &pTarget,
+ DeviceType_HardDisk);
if (FAILED(rc)) throw rc;
}
/* This medium becomes the parent of the next medium in the
@@ -1228,13 +1231,17 @@ HRESULT MachineCloneVM::run()
const MEDIUMTASK &mt = mtc.chain.first();
ComObjPtr<Medium> pLMedium = static_cast<Medium*>((IMedium*)mt.pMedium);
if (pLMedium.isNull())
- throw E_POINTER;
+ throw p->setError(VBOX_E_OBJECT_NOT_FOUND);
ComObjPtr<Medium> pBase = pLMedium->getBase();
if (pBase->isReadOnly())
{
ComObjPtr<Medium> pDiff;
- rc = d->createDifferencingMedium(pNewParent, strTrgSnapshotFolder,
+ trgLock.release();
+ srcLock.release();
+ rc = d->createDifferencingMedium(p, pNewParent, strTrgSnapshotFolder,
newMedia, &pDiff);
+ srcLock.acquire();
+ trgLock.acquire();
if (FAILED(rc)) throw rc;
/* diff image has to be used... */
pNewParent = pDiff;
@@ -1271,7 +1278,15 @@ HRESULT MachineCloneVM::run()
if (FAILED(mac2.rc())) throw mac2.rc();
AutoReadLock mlock2(pParent COMMA_LOCKVAL_SRC_POS);
if (pParent->getFirstRegistryMachineId(uuid))
- VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, uuid);
+ {
+ mlock2.release();
+ trgLock.release();
+ srcLock.release();
+ p->mParent->markRegistryModified(uuid);
+ srcLock.acquire();
+ trgLock.acquire();
+ mlock2.acquire();
+ }
}
mlock.acquire();
}
@@ -1342,7 +1357,7 @@ HRESULT MachineCloneVM::run()
}
/* Any additional machines need saving? */
- p->mParent->saveRegistries(llRegistriesThatNeedSaving);
+ p->mParent->saveModifiedRegistries();
}
catch (HRESULT rc2)
{
@@ -1350,7 +1365,7 @@ HRESULT MachineCloneVM::run()
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(p, RT_SRC_POS);
}
MultiResult mrc(rc);
@@ -1371,8 +1386,7 @@ HRESULT MachineCloneVM::run()
{
const ComObjPtr<Medium> &pMedium = newMedia.at(i - 1);
mrc = pMedium->deleteStorage(NULL /* aProgress */,
- true /* aWait */,
- NULL /* llRegistriesThatNeedSaving */);
+ true /* aWait */);
pMedium->Close();
}
/* Delete the snapshot folder when not empty. */
@@ -1380,6 +1394,9 @@ HRESULT MachineCloneVM::run()
RTDirRemove(strTrgSnapshotFolder.c_str());
/* Delete the machine folder when not empty. */
RTDirRemove(strTrgMachineFolder.c_str());
+
+ /* Must save the modified registries */
+ p->mParent->saveModifiedRegistries();
}
return mrc;
diff --git a/src/VBox/Main/src-server/MediumAttachmentImpl.cpp b/src/VBox/Main/src-server/MediumAttachmentImpl.cpp
index 0ad663de4..26dfeb34f 100644
--- a/src/VBox/Main/src-server/MediumAttachmentImpl.cpp
+++ b/src/VBox/Main/src-server/MediumAttachmentImpl.cpp
@@ -41,6 +41,7 @@ struct BackupableMediumAttachmentData
fPassthrough(false),
fTempEject(false),
fNonRotational(false),
+ fDiscard(false),
fImplicit(false)
{ }
@@ -59,6 +60,7 @@ struct BackupableMediumAttachmentData
bool fPassthrough;
bool fTempEject;
bool fNonRotational;
+ bool fDiscard;
bool fImplicit;
};
@@ -119,6 +121,7 @@ HRESULT MediumAttachment::init(Machine *aParent,
bool aPassthrough,
bool aTempEject,
bool aNonRotational,
+ bool aDiscard,
const Utf8Str &strBandwidthGroup)
{
LogFlowThisFuncEnter();
@@ -146,6 +149,7 @@ HRESULT MediumAttachment::init(Machine *aParent,
m->bd->fPassthrough = aPassthrough;
m->bd->fTempEject = aTempEject;
m->bd->fNonRotational = aNonRotational;
+ m->bd->fDiscard = aDiscard;
m->bd->fImplicit = aImplicit;
/* Confirm a successful initialization when it's the case */
@@ -369,6 +373,23 @@ STDMETHODIMP MediumAttachment::COMGETTER(NonRotational)(BOOL *aNonRotational)
return S_OK;
}
+STDMETHODIMP MediumAttachment::COMGETTER(Discard)(BOOL *aDiscard)
+{
+ LogFlowThisFuncEnter();
+
+ CheckComArgOutPointerValid(aDiscard);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
+
+ *aDiscard = m->bd->fDiscard;
+
+ LogFlowThisFuncLeave();
+ return S_OK;
+}
+
STDMETHODIMP MediumAttachment::COMGETTER(BandwidthGroup) (IBandwidthGroup **aBwGroup)
{
LogFlowThisFuncEnter();
@@ -485,6 +506,12 @@ bool MediumAttachment::getNonRotational() const
return m->bd->fNonRotational;
}
+bool MediumAttachment::getDiscard() const
+{
+ AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
+ return m->bd->fDiscard;
+}
+
const Utf8Str& MediumAttachment::getBandwidthGroup() const
{
return m->bd->strBandwidthGroup;
@@ -546,6 +573,15 @@ void MediumAttachment::updateNonRotational(bool aNonRotational)
m->bd->fNonRotational = aNonRotational;
}
+/** Must be called from under this object's write lock. */
+void MediumAttachment::updateDiscard(bool aDiscard)
+{
+ Assert(isWriteLockOnCurrentThread());
+
+ m->bd.backup();
+ m->bd->fDiscard = aDiscard;
+}
+
void MediumAttachment::updateBandwidthGroup(const Utf8Str &aBandwidthGroup)
{
LogFlowThisFuncEnter();
diff --git a/src/VBox/Main/src-server/MediumImpl.cpp b/src/VBox/Main/src-server/MediumImpl.cpp
index 41c239165..e942227e7 100644
--- a/src/VBox/Main/src-server/MediumImpl.cpp
+++ b/src/VBox/Main/src-server/MediumImpl.cpp
@@ -39,6 +39,9 @@
#include <VBox/vd.h>
#include <algorithm>
+#include <list>
+
+typedef std::list<Guid> GuidList;
////////////////////////////////////////////////////////////////////////////////
//
@@ -87,7 +90,7 @@ struct Medium::Data
size(0),
readers(0),
preLockState(MediumState_NotCreated),
- queryInfoSem(NIL_RTSEMEVENTMULTI),
+ queryInfoSem(LOCKCLASS_MEDIUMQUERY),
queryInfoRunning(false),
type(MediumType_Normal),
devType(DeviceType_HardDisk),
@@ -124,7 +127,12 @@ struct Medium::Data
size_t readers;
MediumState_T preLockState;
- RTSEMEVENTMULTI queryInfoSem;
+ /** Special synchronization for operations which must wait for
+ * Medium::queryInfo in another thread to complete. Using a SemRW is
+ * not quite ideal, but at least it is subject to the lock validator,
+ * unlike the SemEventMulti which we had here for many years. Catching
+ * possible deadlocks is more important than a tiny bit of efficiency. */
+ RWLockHandle queryInfoSem;
bool queryInfoRunning : 1;
const Utf8Str strFormat;
@@ -138,9 +146,9 @@ struct Medium::Data
bool autoReset : 1;
- /** New UUID to be set on the next queryInfo() call. */
+ /** New UUID to be set on the next Medium::queryInfo call. */
const Guid uuidImage;
- /** New parent UUID to be set on the next queryInfo() call. */
+ /** New parent UUID to be set on the next Medium::queryInfo call. */
const Guid uuidParentImage;
bool hostDrive : 1;
@@ -156,14 +164,11 @@ struct Medium::Data
Utf8Str vdError; /*< Error remembered by the VD error callback. */
- VDINTERFACE vdIfError;
- VDINTERFACEERROR vdIfCallsError;
+ VDINTERFACEERROR vdIfError;
- VDINTERFACE vdIfConfig;
- VDINTERFACECONFIG vdIfCallsConfig;
+ VDINTERFACECONFIG vdIfConfig;
- VDINTERFACE vdIfTcpNet;
- VDINTERFACETCPNET vdIfCallsTcpNet;
+ VDINTERFACETCPNET vdIfTcpNet;
PVDINTERFACE vdDiskIfaces;
PVDINTERFACE vdImageIfaces;
@@ -195,7 +200,6 @@ class Medium::Task
public:
Task(Medium *aMedium, Progress *aProgress)
: mVDOperationIfaces(NULL),
- m_pllRegistriesThatNeedSaving(NULL),
mMedium(aMedium),
mMediumCaller(aMedium),
mThread(NIL_RTTHREAD),
@@ -217,14 +221,12 @@ public:
/* Set up a per-operation progress interface, can be used freely (for
* binary operations you can use it either on the source or target). */
- mVDIfCallsProgress.cbSize = sizeof(VDINTERFACEPROGRESS);
- mVDIfCallsProgress.enmInterface = VDINTERFACETYPE_PROGRESS;
- mVDIfCallsProgress.pfnProgress = vdProgressCall;
- int vrc = VDInterfaceAdd(&mVDIfProgress,
+ mVDIfProgress.pfnProgress = vdProgressCall;
+ int vrc = VDInterfaceAdd(&mVDIfProgress.Core,
"Medium::Task::vdInterfaceProgress",
VDINTERFACETYPE_PROGRESS,
- &mVDIfCallsProgress,
mProgress,
+ sizeof(VDINTERFACEPROGRESS),
&mVDOperationIfaces);
AssertRC(vrc);
if (RT_FAILURE(vrc))
@@ -244,15 +246,10 @@ public:
PVDINTERFACE mVDOperationIfaces;
- // Whether the caller needs to call VirtualBox::saveRegistries() after
- // the task function returns. Only used in synchronous (wait) mode;
- // otherwise the task will save the settings itself.
- GuidList *m_pllRegistriesThatNeedSaving;
-
const ComObjPtr<Medium> mMedium;
AutoCaller mMediumCaller;
- friend HRESULT Medium::runNow(Medium::Task*, GuidList *);
+ friend HRESULT Medium::runNow(Medium::Task*);
protected:
HRESULT mRC;
@@ -265,8 +262,7 @@ private:
static DECLCALLBACK(int) vdProgressCall(void *pvUser, unsigned uPercent);
- VDINTERFACE mVDIfProgress;
- VDINTERFACEPROGRESS mVDIfCallsProgress;
+ VDINTERFACEPROGRESS mVDIfProgress;
/* Must have a strong VirtualBox reference during a task otherwise the
* reference count might drop to 0 while a task is still running. This
@@ -594,7 +590,7 @@ public:
const char *aFilename,
MediumFormat *aFormat,
MediumVariant_T aVariant,
- void *aVDImageIOCallbacks,
+ VDINTERFACEIO *aVDImageIOIf,
void *aVDImageIOUser,
MediumLockList *aSourceMediumLockList,
bool fKeepSourceMediumLockList = false)
@@ -608,11 +604,11 @@ public:
AssertReturnVoidStmt(aSourceMediumLockList != NULL, mRC = E_FAIL);
mVDImageIfaces = aMedium->m->vdImageIfaces;
- if (aVDImageIOCallbacks)
+ if (aVDImageIOIf)
{
- int vrc = VDInterfaceAdd(&mVDInterfaceIO, "Medium::vdInterfaceIO",
- VDINTERFACETYPE_IO, aVDImageIOCallbacks,
- aVDImageIOUser, &mVDImageIfaces);
+ int vrc = VDInterfaceAdd(&aVDImageIOIf->Core, "Medium::vdInterfaceIO",
+ VDINTERFACETYPE_IO, aVDImageIOUser,
+ sizeof(VDINTERFACEIO), &mVDImageIfaces);
AssertRCReturnVoidStmt(vrc, mRC = E_FAIL);
}
}
@@ -633,7 +629,6 @@ private:
virtual HRESULT handler();
bool mfKeepSourceMediumLockList;
- VDINTERFACE mVDInterfaceIO;
};
class Medium::ImportTask : public Medium::Task
@@ -644,7 +639,7 @@ public:
const char *aFilename,
MediumFormat *aFormat,
MediumVariant_T aVariant,
- void *aVDImageIOCallbacks,
+ VDINTERFACEIO *aVDImageIOIf,
void *aVDImageIOUser,
Medium *aParent,
MediumLockList *aTargetMediumLockList,
@@ -665,11 +660,11 @@ public:
return;
mVDImageIfaces = aMedium->m->vdImageIfaces;
- if (aVDImageIOCallbacks)
+ if (aVDImageIOIf)
{
- int vrc = VDInterfaceAdd(&mVDInterfaceIO, "Medium::vdInterfaceIO",
- VDINTERFACETYPE_IO, aVDImageIOCallbacks,
- aVDImageIOUser, &mVDImageIfaces);
+ int vrc = VDInterfaceAdd(&aVDImageIOIf->Core, "Medium::vdInterfaceIO",
+ VDINTERFACETYPE_IO, aVDImageIOUser,
+ sizeof(VDINTERFACEIO), &mVDImageIfaces);
AssertRCReturnVoidStmt(vrc, mRC = E_FAIL);
}
}
@@ -692,7 +687,6 @@ private:
AutoCaller mParentCaller;
bool mfKeepTargetMediumLockList;
- VDINTERFACE mVDInterfaceIO;
};
/**
@@ -849,63 +843,52 @@ HRESULT Medium::FinalConstruct()
m = new Data;
/* Initialize the callbacks of the VD error interface */
- m->vdIfCallsError.cbSize = sizeof(VDINTERFACEERROR);
- m->vdIfCallsError.enmInterface = VDINTERFACETYPE_ERROR;
- m->vdIfCallsError.pfnError = vdErrorCall;
- m->vdIfCallsError.pfnMessage = NULL;
+ m->vdIfError.pfnError = vdErrorCall;
+ m->vdIfError.pfnMessage = NULL;
/* Initialize the callbacks of the VD config interface */
- m->vdIfCallsConfig.cbSize = sizeof(VDINTERFACECONFIG);
- m->vdIfCallsConfig.enmInterface = VDINTERFACETYPE_CONFIG;
- m->vdIfCallsConfig.pfnAreKeysValid = vdConfigAreKeysValid;
- m->vdIfCallsConfig.pfnQuerySize = vdConfigQuerySize;
- m->vdIfCallsConfig.pfnQuery = vdConfigQuery;
+ m->vdIfConfig.pfnAreKeysValid = vdConfigAreKeysValid;
+ m->vdIfConfig.pfnQuerySize = vdConfigQuerySize;
+ m->vdIfConfig.pfnQuery = vdConfigQuery;
/* Initialize the callbacks of the VD TCP interface (we always use the host
* IP stack for now) */
- m->vdIfCallsTcpNet.cbSize = sizeof(VDINTERFACETCPNET);
- m->vdIfCallsTcpNet.enmInterface = VDINTERFACETYPE_TCPNET;
- m->vdIfCallsTcpNet.pfnSocketCreate = vdTcpSocketCreate;
- m->vdIfCallsTcpNet.pfnSocketDestroy = vdTcpSocketDestroy;
- m->vdIfCallsTcpNet.pfnClientConnect = vdTcpClientConnect;
- m->vdIfCallsTcpNet.pfnClientClose = vdTcpClientClose;
- m->vdIfCallsTcpNet.pfnIsClientConnected = vdTcpIsClientConnected;
- m->vdIfCallsTcpNet.pfnSelectOne = vdTcpSelectOne;
- m->vdIfCallsTcpNet.pfnRead = vdTcpRead;
- m->vdIfCallsTcpNet.pfnWrite = vdTcpWrite;
- m->vdIfCallsTcpNet.pfnSgWrite = vdTcpSgWrite;
- m->vdIfCallsTcpNet.pfnFlush = vdTcpFlush;
- m->vdIfCallsTcpNet.pfnSetSendCoalescing = vdTcpSetSendCoalescing;
- m->vdIfCallsTcpNet.pfnGetLocalAddress = vdTcpGetLocalAddress;
- m->vdIfCallsTcpNet.pfnGetPeerAddress = vdTcpGetPeerAddress;
- m->vdIfCallsTcpNet.pfnSelectOneEx = NULL;
- m->vdIfCallsTcpNet.pfnPoke = NULL;
+ m->vdIfTcpNet.pfnSocketCreate = vdTcpSocketCreate;
+ m->vdIfTcpNet.pfnSocketDestroy = vdTcpSocketDestroy;
+ m->vdIfTcpNet.pfnClientConnect = vdTcpClientConnect;
+ m->vdIfTcpNet.pfnClientClose = vdTcpClientClose;
+ m->vdIfTcpNet.pfnIsClientConnected = vdTcpIsClientConnected;
+ m->vdIfTcpNet.pfnSelectOne = vdTcpSelectOne;
+ m->vdIfTcpNet.pfnRead = vdTcpRead;
+ m->vdIfTcpNet.pfnWrite = vdTcpWrite;
+ m->vdIfTcpNet.pfnSgWrite = vdTcpSgWrite;
+ m->vdIfTcpNet.pfnFlush = vdTcpFlush;
+ m->vdIfTcpNet.pfnSetSendCoalescing = vdTcpSetSendCoalescing;
+ m->vdIfTcpNet.pfnGetLocalAddress = vdTcpGetLocalAddress;
+ m->vdIfTcpNet.pfnGetPeerAddress = vdTcpGetPeerAddress;
+ m->vdIfTcpNet.pfnSelectOneEx = NULL;
+ m->vdIfTcpNet.pfnPoke = NULL;
/* Initialize the per-disk interface chain (could be done more globally,
* but it's not wasting much time or space so it's not worth it). */
int vrc;
- vrc = VDInterfaceAdd(&m->vdIfError,
+ vrc = VDInterfaceAdd(&m->vdIfError.Core,
"Medium::vdInterfaceError",
- VDINTERFACETYPE_ERROR,
- &m->vdIfCallsError, this, &m->vdDiskIfaces);
+ VDINTERFACETYPE_ERROR, this,
+ sizeof(VDINTERFACEERROR), &m->vdDiskIfaces);
AssertRCReturn(vrc, E_FAIL);
/* Initialize the per-image interface chain */
- vrc = VDInterfaceAdd(&m->vdIfConfig,
+ vrc = VDInterfaceAdd(&m->vdIfConfig.Core,
"Medium::vdInterfaceConfig",
- VDINTERFACETYPE_CONFIG,
- &m->vdIfCallsConfig, this, &m->vdImageIfaces);
+ VDINTERFACETYPE_CONFIG, this,
+ sizeof(VDINTERFACECONFIG), &m->vdImageIfaces);
AssertRCReturn(vrc, E_FAIL);
- vrc = VDInterfaceAdd(&m->vdIfTcpNet,
+ vrc = VDInterfaceAdd(&m->vdIfTcpNet.Core,
"Medium::vdInterfaceTcpNet",
- VDINTERFACETYPE_TCPNET,
- &m->vdIfCallsTcpNet, this, &m->vdImageIfaces);
- AssertRCReturn(vrc, E_FAIL);
-
- vrc = RTSemEventMultiCreate(&m->queryInfoSem);
- AssertRCReturn(vrc, E_FAIL);
- vrc = RTSemEventMultiSignal(m->queryInfoSem);
+ VDINTERFACETYPE_TCPNET, this,
+ sizeof(VDINTERFACETCPNET), &m->vdImageIfaces);
AssertRCReturn(vrc, E_FAIL);
return BaseFinalConstruct();
@@ -941,13 +924,11 @@ void Medium::FinalRelease()
* @param aFormat
* @param aLocation Storage unit location.
* @param uuidMachineRegistry The registry to which this medium should be added (global registry UUID or machine UUID or empty if none).
- * @param pllRegistriesThatNeedSaving Optional list to receive the UUIDs of the media registries that need saving.
*/
HRESULT Medium::init(VirtualBox *aVirtualBox,
const Utf8Str &aFormat,
const Utf8Str &aLocation,
- const Guid &uuidMachineRegistry,
- GuidList *pllRegistriesThatNeedSaving)
+ const Guid &uuidMachineRegistry)
{
AssertReturn(aVirtualBox != NULL, E_FAIL);
AssertReturn(!aFormat.isEmpty(), E_FAIL);
@@ -969,7 +950,7 @@ HRESULT Medium::init(VirtualBox *aVirtualBox,
/* cannot be a host drive */
m->hostDrive = false;
- /* No storage unit is created yet, no need to queryInfo() */
+ /* No storage unit is created yet, no need to call Medium::queryInfo */
rc = setFormat(aFormat);
if (FAILED(rc)) return rc;
@@ -992,7 +973,7 @@ HRESULT Medium::init(VirtualBox *aVirtualBox,
AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
ComObjPtr<Medium> pMedium;
- rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk, pllRegistriesThatNeedSaving);
+ rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk);
Assert(this == pMedium);
}
@@ -1037,60 +1018,89 @@ HRESULT Medium::init(VirtualBox *aVirtualBox,
AssertReturn(aVirtualBox, E_INVALIDARG);
AssertReturn(!aLocation.isEmpty(), E_INVALIDARG);
- /* Enclose the state transition NotReady->InInit->Ready */
- AutoInitSpan autoInitSpan(this);
- AssertReturn(autoInitSpan.isOk(), E_FAIL);
-
HRESULT rc = S_OK;
- unconst(m->pVirtualBox) = aVirtualBox;
+ {
+ /* Enclose the state transition NotReady->InInit->Ready */
+ AutoInitSpan autoInitSpan(this);
+ AssertReturn(autoInitSpan.isOk(), E_FAIL);
- /* there must be a storage unit */
- m->state = MediumState_Created;
+ unconst(m->pVirtualBox) = aVirtualBox;
- /* remember device type for correct unregistering later */
- m->devType = aDeviceType;
+ /* there must be a storage unit */
+ m->state = MediumState_Created;
- /* cannot be a host drive */
- m->hostDrive = false;
+ /* remember device type for correct unregistering later */
+ m->devType = aDeviceType;
- /* remember the open mode (defaults to ReadWrite) */
- m->hddOpenMode = enOpenMode;
+ /* cannot be a host drive */
+ m->hostDrive = false;
- if (aDeviceType == DeviceType_DVD)
- m->type = MediumType_Readonly;
- else if (aDeviceType == DeviceType_Floppy)
- m->type = MediumType_Writethrough;
+ /* remember the open mode (defaults to ReadWrite) */
+ m->hddOpenMode = enOpenMode;
- rc = setLocation(aLocation);
- if (FAILED(rc)) return rc;
+ if (aDeviceType == DeviceType_DVD)
+ m->type = MediumType_Readonly;
+ else if (aDeviceType == DeviceType_Floppy)
+ m->type = MediumType_Writethrough;
- /* get all the information about the medium from the storage unit */
- if (fForceNewUuid)
- unconst(m->uuidImage).create();
- rc = queryInfo(fForceNewUuid /* fSetImageId */, false /* fSetParentId */);
+ rc = setLocation(aLocation);
+ if (FAILED(rc)) return rc;
+
+ /* get all the information about the medium from the storage unit */
+ if (fForceNewUuid)
+ unconst(m->uuidImage).create();
+
+ m->state = MediumState_Inaccessible;
+ m->strLastAccessError = tr("Accessibility check was not yet performed");
+
+ /* Confirm a successful initialization before the call to queryInfo.
+ * Otherwise we can end up with a AutoCaller deadlock because the
+ * medium becomes visible but is not marked as initialized. Causes
+ * locking trouble (e.g. trying to save media registries) which is
+ * hard to solve. */
+ autoInitSpan.setSucceeded();
+ }
+
+ /* we're normal code from now on, no longer init */
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
+ /* need to call queryInfo immediately to correctly place the medium in
+ * the respective media tree and update other information such as uuid */
+ rc = queryInfo(fForceNewUuid /* fSetImageId */, false /* fSetParentId */);
if (SUCCEEDED(rc))
{
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
/* if the storage unit is not accessible, it's not acceptable for the
* newly opened media so convert this into an error */
if (m->state == MediumState_Inaccessible)
{
Assert(!m->strLastAccessError.isEmpty());
rc = setError(E_FAIL, "%s", m->strLastAccessError.c_str());
+ alock.release();
+ autoCaller.release();
+ uninit();
}
else
{
- AssertReturn(!m->id.isEmpty(), E_FAIL);
+ AssertStmt(!m->id.isEmpty(),
+ alock.release(); autoCaller.release(); uninit(); return E_FAIL);
- /* storage format must be detected by queryInfo() if the medium is accessible */
- AssertReturn(!m->strFormat.isEmpty(), E_FAIL);
+ /* storage format must be detected by Medium::queryInfo if the
+ * medium is accessible */
+ AssertStmt(!m->strFormat.isEmpty(),
+ alock.release(); autoCaller.release(); uninit(); return E_FAIL);
}
}
-
- /* Confirm a successful initialization when it's the case */
- if (SUCCEEDED(rc))
- autoInitSpan.setSucceeded();
+ else
+ {
+ /* opening this image failed, mark the object as dead */
+ autoCaller.release();
+ uninit();
+ }
return rc;
}
@@ -1144,8 +1154,8 @@ HRESULT Medium::init(VirtualBox *aVirtualBox,
aParent->m->llChildren.push_back(this);
}
- /* see below why we don't call queryInfo() (and therefore treat the medium
- * as inaccessible for now */
+ /* see below why we don't call Medium::queryInfo (and therefore treat
+ * the medium as inaccessible for now */
m->state = MediumState_Inaccessible;
m->strLastAccessError = tr("Accessibility check was not yet performed");
@@ -1196,6 +1206,17 @@ HRESULT Medium::init(VirtualBox *aVirtualBox,
m->mapProperties[name] = value;
}
+ /* try to decrypt an optional iSCSI initiator secret */
+ settings::StringsMap::const_iterator itCph = data.properties.find("InitiatorSecretEncrypted");
+ if ( itCph != data.properties.end()
+ && !itCph->second.isEmpty())
+ {
+ Utf8Str strPlaintext;
+ int vrc = m->pVirtualBox->decryptSetting(&strPlaintext, itCph->second);
+ if (RT_SUCCESS(vrc))
+ m->mapProperties["InitiatorSecret"] = strPlaintext;
+ }
+
Utf8Str strFull;
if (m->formatObj->getCapabilities() & MediumFormatCapabilities_File)
{
@@ -1240,7 +1261,7 @@ HRESULT Medium::init(VirtualBox *aVirtualBox,
LogFlowThisFunc(("m->strLocationFull='%s', m->strFormat=%s, m->id={%RTuuid}\n",
m->strLocationFull.c_str(), m->strFormat.c_str(), m->id.raw()));
- /* Don't call queryInfo() for registered media to prevent the calling
+ /* Don't call Medium::queryInfo for registered media to prevent the calling
* thread (i.e. the VirtualBox server startup thread) from an unexpected
* freeze but mark it as initially inaccessible instead. The vital UUID,
* location and format properties are read from the registry file above; to
@@ -1266,7 +1287,7 @@ HRESULT Medium::init(VirtualBox *aVirtualBox,
strMachineFolder);
if (FAILED(rc)) break;
- rc = m->pVirtualBox->registerMedium(pHD, &pHD, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */ );
+ rc = m->pVirtualBox->registerMedium(pHD, &pHD, DeviceType_HardDisk);
if (FAILED(rc)) break;
}
@@ -1345,8 +1366,6 @@ HRESULT Medium::init(VirtualBox *aVirtualBox,
*
* @note All children of this medium get uninitialized by calling their
* uninit() methods.
- *
- * @note Caller must hold the tree lock of the medium tree this medium is on.
*/
void Medium::uninit()
{
@@ -1388,10 +1407,6 @@ void Medium::uninit()
}
}
- RTSemEventMultiSignal(m->queryInfoSem);
- RTSemEventMultiDestroy(m->queryInfoSem);
- m->queryInfoSem = NIL_RTSEMEVENTMULTI;
-
unconst(m->pVirtualBox) = NULL;
}
@@ -1646,8 +1661,8 @@ STDMETHODIMP Medium::COMSETTER(Type)(MediumType_T aType)
if (FAILED(autoCaller.rc())) return autoCaller.rc();
// we access mParent and members
- AutoMultiWriteLock2 mlock(&m->pVirtualBox->getMediaTreeLockHandle(),
- this->lockHandle() COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
switch (m->state)
{
@@ -1721,15 +1736,6 @@ STDMETHODIMP Medium::COMSETTER(Type)(MediumType_T aType)
m->strLocationFull.c_str(), getChildren().size());
if (aType == MediumType_Shareable)
{
- if (m->state == MediumState_Inaccessible)
- {
- HRESULT rc = queryInfo(false /* fSetImageId */, false /* fSetParentId */);
- if (FAILED(rc))
- return setError(rc,
- tr("Cannot change type for medium '%s' to 'Shareable' because the medium is inaccessible"),
- m->strLocationFull.c_str());
- }
-
MediumVariant_T variant = getVariant();
if (!(variant & MediumVariant_Fixed))
return setError(VBOX_E_INVALID_OBJECT_STATE,
@@ -1773,10 +1779,10 @@ STDMETHODIMP Medium::COMSETTER(Type)(MediumType_T aType)
m->type = aType;
// save the settings
- GuidList llRegistriesThatNeedSaving;
- addToRegistryIDList(llRegistriesThatNeedSaving);
mlock.release();
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ treeLock.release();
+ markRegistriesModified();
+ m->pVirtualBox->saveModifiedRegistries();
return S_OK;
}
@@ -1784,6 +1790,10 @@ STDMETHODIMP Medium::COMSETTER(Type)(MediumType_T aType)
STDMETHODIMP Medium::COMGETTER(AllowedTypes)(ComSafeArrayOut(MediumType_T, aAllowedTypes))
{
CheckComArgOutSafeArrayPointerValid(aAllowedTypes);
+ NOREF(aAllowedTypes);
+#ifndef RT_OS_WINDOWS
+ NOREF(aAllowedTypesSize);
+#endif
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1913,10 +1923,9 @@ STDMETHODIMP Medium::COMSETTER(AutoReset)(BOOL aAutoReset)
m->autoReset = !!aAutoReset;
// save the settings
- GuidList llRegistriesThatNeedSaving;
- addToRegistryIDList(llRegistriesThatNeedSaving);
mlock.release();
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ markRegistriesModified();
+ m->pVirtualBox->saveModifiedRegistries();
}
return S_OK;
@@ -1964,7 +1973,7 @@ STDMETHODIMP Medium::COMGETTER(MachineIds)(ComSafeArrayOut(BSTR,aMachineIds))
return S_OK;
}
-STDMETHODIMP Medium::SetIDs(BOOL aSetImageId,
+STDMETHODIMP Medium::SetIds(BOOL aSetImageId,
IN_BSTR aImageId,
BOOL aSetParentId,
IN_BSTR aParentId)
@@ -2005,6 +2014,9 @@ STDMETHODIMP Medium::SetIDs(BOOL aSetImageId,
unconst(m->uuidImage) = imageId;
unconst(m->uuidParentImage) = parentId;
+ // must not hold any locks before calling Medium::queryInfo
+ alock.release();
+
HRESULT rc = queryInfo(!!aSetImageId /* fSetImageId */,
!!aSetParentId /* fSetParentId */);
@@ -2018,8 +2030,7 @@ STDMETHODIMP Medium::RefreshState(MediumState_T *aState)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* queryInfo() locks this for writing. */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = S_OK;
@@ -2029,7 +2040,12 @@ STDMETHODIMP Medium::RefreshState(MediumState_T *aState)
case MediumState_Inaccessible:
case MediumState_LockedRead:
{
+ // must not hold any locks before calling Medium::queryInfo
+ alock.release();
+
rc = queryInfo(false /* fSetImageId */, false /* fSetParentId */);
+
+ alock.acquire();
break;
}
default:
@@ -2101,14 +2117,24 @@ STDMETHODIMP Medium::LockRead(MediumState_T *aState)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ /* Must not hold the object lock, as we need control over it below. */
+ Assert(!isWriteLockOnCurrentThread());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Wait for a concurrently running queryInfo() to complete */
- while (m->queryInfoRunning)
+ /* Wait for a concurrently running Medium::queryInfo to complete. */
+ if (m->queryInfoRunning)
{
- alock.leave();
- RTSemEventMultiWait(m->queryInfoSem, RT_INDEFINITE_WAIT);
- alock.enter();
+ /* Must not hold the media tree lock, as Medium::queryInfo needs this
+ * lock and thus we would run into a deadlock here. */
+ Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
+ while (m->queryInfoRunning)
+ {
+ alock.release();
+ {
+ AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
+ }
+ alock.acquire();
+ }
}
/* return the current state before */
@@ -2164,7 +2190,7 @@ STDMETHODIMP Medium::UnlockRead(MediumState_T *aState)
{
case MediumState_LockedRead:
{
- Assert(m->readers != 0);
+ ComAssertMsgBreak(m->readers != 0, ("Counter underflow"), rc = E_FAIL);
--m->readers;
/* Reset the state after the last reader */
@@ -2207,14 +2233,24 @@ STDMETHODIMP Medium::LockWrite(MediumState_T *aState)
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ /* Must not hold the object lock, as we need control over it below. */
+ Assert(!isWriteLockOnCurrentThread());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Wait for a concurrently running queryInfo() to complete */
- while (m->queryInfoRunning)
+ /* Wait for a concurrently running Medium::queryInfo to complete. */
+ if (m->queryInfoRunning)
{
- alock.leave();
- RTSemEventMultiWait(m->queryInfoSem, RT_INDEFINITE_WAIT);
- alock.enter();
+ /* Must not hold the media tree lock, as Medium::queryInfo needs this
+ * lock and thus we would run into a deadlock here. */
+ Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
+ while (m->queryInfoRunning)
+ {
+ alock.release();
+ {
+ AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
+ }
+ alock.acquire();
+ }
}
/* return the current state before */
@@ -2296,10 +2332,9 @@ STDMETHODIMP Medium::Close()
// make a copy of VirtualBox pointer which gets nulled by uninit()
ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox);
- GuidList llRegistriesThatNeedSaving;
- MultiResult mrc = close(&llRegistriesThatNeedSaving, autoCaller);
- /* Must save the registries, since an entry was most likely removed. */
- pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ MultiResult mrc = close(autoCaller);
+
+ pVirtualBox->saveModifiedRegistries();
return mrc;
}
@@ -2351,10 +2386,9 @@ STDMETHODIMP Medium::SetProperty(IN_BSTR aName, IN_BSTR aValue)
it->second = aValue;
// save the settings
- GuidList llRegistriesThatNeedSaving;
- addToRegistryIDList(llRegistriesThatNeedSaving);
mlock.release();
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ markRegistriesModified();
+ m->pVirtualBox->saveModifiedRegistries();
return S_OK;
}
@@ -2429,10 +2463,9 @@ STDMETHODIMP Medium::SetProperties(ComSafeArrayIn(IN_BSTR, aNames),
}
// save the settings
- GuidList llRegistriesThatNeedSaving;
- addToRegistryIDList(llRegistriesThatNeedSaving);
mlock.release();
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ markRegistriesModified();
+ m->pVirtualBox->saveModifiedRegistries();
return S_OK;
}
@@ -2515,12 +2548,10 @@ STDMETHODIMP Medium::DeleteStorage(IProgress **aProgress)
ComObjPtr<Progress> pProgress;
- GuidList llRegistriesThatNeedSaving;
MultiResult mrc = deleteStorage(&pProgress,
- false /* aWait */,
- &llRegistriesThatNeedSaving);
+ false /* aWait */);
/* Must save the registries in any case, since an entry was removed. */
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ m->pVirtualBox->saveModifiedRegistries();
if (SUCCEEDED(mrc))
pProgress.queryInterfaceTo(aProgress);
@@ -2541,8 +2572,8 @@ STDMETHODIMP Medium::CreateDiffStorage(IMedium *aTarget,
ComObjPtr<Medium> diff = static_cast<Medium*>(aTarget);
// locking: we need the tree lock first because we access parent pointers
- AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
- AutoMultiWriteLock2 alock(this, diff COMMA_LOCKVAL_SRC_POS);
+ AutoMultiWriteLock3 alock(&m->pVirtualBox->getMediaTreeLockHandle(),
+ this->lockHandle(), diff->lockHandle() COMMA_LOCKVAL_SRC_POS);
if (m->type == MediumType_Writethrough)
return setError(VBOX_E_INVALID_OBJECT_STATE,
@@ -2559,17 +2590,21 @@ STDMETHODIMP Medium::CreateDiffStorage(IMedium *aTarget,
/* Apply the normal locking logic to the entire chain. */
MediumLockList *pMediumLockList(new MediumLockList());
+ alock.release();
HRESULT rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
this,
*pMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
return rc;
}
+ alock.release();
rc = pMediumLockList->Lock();
+ alock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
@@ -2583,16 +2618,17 @@ STDMETHODIMP Medium::CreateDiffStorage(IMedium *aTarget,
{
/* since this medium has been just created it isn't associated yet */
diff->m->llRegistryIDs.push_back(parentMachineRegistry);
+ alock.release();
+ diff->markRegistriesModified();
+ alock.acquire();
}
- treeLock.release();
alock.release();
ComObjPtr <Progress> pProgress;
rc = createDiffStorage(diff, (MediumVariant_T)aVariant, pMediumLockList,
- &pProgress, false /* aWait */,
- NULL /* pllRegistriesThatNeedSaving */);
+ &pProgress, false /* aWait */);
if (FAILED(rc))
delete pMediumLockList;
else
@@ -2626,8 +2662,7 @@ STDMETHODIMP Medium::MergeTo(IMedium *aTarget, IProgress **aProgress)
ComObjPtr <Progress> pProgress;
rc = mergeTo(pTarget, fMergeForward, pParentForTarget, childrenToReparent,
- pMediumLockList, &pProgress, false /* aWait */,
- NULL /* pllRegistriesThatNeedSaving */);
+ pMediumLockList, &pProgress, false /* aWait */);
if (FAILED(rc))
cancelMergeTo(childrenToReparent, pMediumLockList);
else
@@ -2636,6 +2671,17 @@ STDMETHODIMP Medium::MergeTo(IMedium *aTarget, IProgress **aProgress)
return rc;
}
+STDMETHODIMP Medium::CloneToBase(IMedium *aTarget,
+ ULONG aVariant,
+ IProgress **aProgress)
+{
+ int rc = S_OK;
+ CheckComArgNotNull(aTarget);
+ CheckComArgOutPointerValid(aProgress);
+ rc = CloneTo(aTarget, aVariant, NULL, aProgress);
+ return rc;
+}
+
STDMETHODIMP Medium::CloneTo(IMedium *aTarget,
ULONG aVariant,
IMedium *aParent,
@@ -2660,9 +2706,17 @@ STDMETHODIMP Medium::CloneTo(IMedium *aTarget,
try
{
// locking: we need the tree lock first because we access parent pointers
- AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
// and we need to write-lock the media involved
- AutoMultiWriteLock3 alock(this, pTarget, pParent COMMA_LOCKVAL_SRC_POS);
+ uint32_t cHandles = 3;
+ LockHandle* pHandles[4] = { &m->pVirtualBox->getMediaTreeLockHandle(),
+ this->lockHandle(),
+ pTarget->lockHandle() };
+ /* Only add parent to the lock if it is not null */
+ if (!pParent.isNull())
+ pHandles[cHandles++] = pParent->lockHandle();
+ AutoWriteLock alock(cHandles,
+ pHandles
+ COMMA_LOCKVAL_SRC_POS);
if ( pTarget->m->state != MediumState_NotCreated
&& pTarget->m->state != MediumState_Created)
@@ -2670,10 +2724,12 @@ STDMETHODIMP Medium::CloneTo(IMedium *aTarget,
/* Build the source lock list. */
MediumLockList *pSourceMediumLockList(new MediumLockList());
+ alock.release();
rc = createMediumLockList(true /* fFailIfInaccessible */,
false /* fMediumLockWrite */,
NULL,
*pSourceMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pSourceMediumLockList;
@@ -2682,10 +2738,12 @@ STDMETHODIMP Medium::CloneTo(IMedium *aTarget,
/* Build the target lock list (including the to-be parent chain). */
MediumLockList *pTargetMediumLockList(new MediumLockList());
+ alock.release();
rc = pTarget->createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
pParent,
*pTargetMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pSourceMediumLockList;
@@ -2693,7 +2751,9 @@ STDMETHODIMP Medium::CloneTo(IMedium *aTarget,
throw rc;
}
+ alock.release();
rc = pSourceMediumLockList->Lock();
+ alock.acquire();
if (FAILED(rc))
{
delete pSourceMediumLockList;
@@ -2702,7 +2762,9 @@ STDMETHODIMP Medium::CloneTo(IMedium *aTarget,
tr("Failed to lock source media '%s'"),
getLocationFull().c_str());
}
+ alock.release();
rc = pTargetMediumLockList->Lock();
+ alock.acquire();
if (FAILED(rc))
{
delete pSourceMediumLockList;
@@ -2765,25 +2827,25 @@ STDMETHODIMP Medium::Compact(IProgress **aProgress)
try
{
- /* We need to lock both the current object, and the tree lock (would
- * cause a lock order violation otherwise) for createMediumLockList. */
- AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
- this->lockHandle()
- COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
/* Build the medium lock list. */
MediumLockList *pMediumLockList(new MediumLockList());
+ alock.release();
rc = createMediumLockList(true /* fFailIfInaccessible */ ,
true /* fMediumLockWrite */,
NULL,
*pMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
throw rc;
}
+ alock.release();
rc = pMediumLockList->Lock();
+ alock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
@@ -2838,25 +2900,25 @@ STDMETHODIMP Medium::Resize(LONG64 aLogicalSize, IProgress **aProgress)
try
{
- /* We need to lock both the current object, and the tree lock (would
- * cause a lock order violation otherwise) for createMediumLockList. */
- AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
- this->lockHandle()
- COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
/* Build the medium lock list. */
MediumLockList *pMediumLockList(new MediumLockList());
+ alock.release();
rc = createMediumLockList(true /* fFailIfInaccessible */ ,
true /* fMediumLockWrite */,
NULL,
*pMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
throw rc;
}
+ alock.release();
rc = pMediumLockList->Lock();
+ alock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
@@ -2929,22 +2991,21 @@ STDMETHODIMP Medium::Reset(IProgress **aProgress)
/* Build the medium lock list. */
MediumLockList *pMediumLockList(new MediumLockList());
+ multilock.release();
rc = createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
NULL,
*pMediumLockList);
+ multilock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
throw rc;
}
- /* Temporary leave this lock, cause IMedium::LockWrite, will wait for
- * an running IMedium::queryInfo. If there is one running it might be
- * it tries to acquire a MediaTreeLock as well -> dead-lock. */
- multilock.leave();
+ multilock.release();
rc = pMediumLockList->Lock();
- multilock.enter();
+ multilock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
@@ -3306,25 +3367,27 @@ bool Medium::getFirstRegistryMachineId(Guid &uuid) const
}
/**
- * Adds all the IDs of the registries in which this medium is registered to the given list
- * of UUIDs, but only if they are not on the list yet.
- * @param llRegistryIDs
+ * Marks all the registries in which this medium is registered as modified.
*/
-HRESULT Medium::addToRegistryIDList(GuidList &llRegistryIDs)
+void Medium::markRegistriesModified()
{
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return false;
+ if (FAILED(autoCaller.rc())) return;
- AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ // Get local copy, as keeping the lock over VirtualBox::markRegistryModified
+ // causes trouble with the lock order
+ GuidList llRegistryIDs;
+ {
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ llRegistryIDs = m->llRegistryIDs;
+ }
- for (GuidList::const_iterator it = m->llRegistryIDs.begin();
- it != m->llRegistryIDs.end();
+ for (GuidList::const_iterator it = llRegistryIDs.begin();
+ it != llRegistryIDs.end();
++it)
{
- VirtualBox::addGuidToListUniquely(llRegistryIDs, *it);
+ m->pVirtualBox->markRegistryModified(*it);
}
-
- return S_OK;
}
/**
@@ -3416,7 +3479,8 @@ HRESULT Medium::addBackReference(const Guid &aMachineId,
}
it->llSnapshotIds.push_back(aSnapshotId);
- it->fInCurState = false;
+ // Do not touch fInCurState, as the image may be attached to the current
+ // state *and* a snapshot, otherwise we lose the current state association!
LogFlowThisFuncLeave();
@@ -3585,9 +3649,12 @@ HRESULT Medium::updatePath(const Utf8Str &strOldPath, const Utf8Str &strNewPath)
unconst(m->strLocationFull) = newPath;
LogFlowThisFunc(("locationFull.after='%s'\n", m->strLocationFull.c_str()));
+ // we changed something
+ return S_OK;
}
- return S_OK;
+ // no change was necessary, signal error which the caller needs to interpret
+ return VBOX_E_FILE_ERROR;
}
/**
@@ -3736,6 +3803,20 @@ HRESULT Medium::saveSettings(settings::Medium &data,
/* optional properties */
data.properties.clear();
+
+ /* handle iSCSI initiator secrets transparently */
+ bool fHaveInitiatorSecretEncrypted = false;
+ Utf8Str strCiphertext;
+ settings::StringsMap::const_iterator itPln = m->mapProperties.find("InitiatorSecret");
+ if ( itPln != m->mapProperties.end()
+ && !itPln->second.isEmpty())
+ {
+ /* Encrypt the plain secret. If that does not work (i.e. no or wrong settings key
+ * specified), just use the encrypted secret (if there is any). */
+ int rc = m->pVirtualBox->encryptSetting(itPln->second, &strCiphertext);
+ if (RT_SUCCESS(rc))
+ fHaveInitiatorSecretEncrypted = true;
+ }
for (settings::StringsMap::const_iterator it = m->mapProperties.begin();
it != m->mapProperties.end();
++it)
@@ -3745,9 +3826,14 @@ HRESULT Medium::saveSettings(settings::Medium &data,
{
const Utf8Str &name = it->first;
const Utf8Str &value = it->second;
- data.properties[name] = value;
+ /* do NOT store the plain InitiatorSecret */
+ if ( !fHaveInitiatorSecretEncrypted
+ || !name.equals("InitiatorSecret"))
+ data.properties[name] = value;
}
}
+ if (fHaveInitiatorSecretEncrypted)
+ data.properties["InitiatorSecretEncrypted"] = strCiphertext;
/* only for base media */
if (m->pParent.isNull())
@@ -3770,7 +3856,7 @@ HRESULT Medium::saveSettings(settings::Medium &data,
/**
* Constructs a medium lock list for this medium. The lock is not taken.
*
- * @note Locks the medium tree for reading.
+ * @note Caller MUST NOT hold the media tree or medium lock.
*
* @param fFailIfInaccessible If true, this fails with an error if a medium is inaccessible. If false,
* inaccessible media are silently skipped and not locked (i.e. their state remains "Inaccessible");
@@ -3784,14 +3870,14 @@ HRESULT Medium::createMediumLockList(bool fFailIfInaccessible,
Medium *pToBeParent,
MediumLockList &mediumLockList)
{
+ Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
+ Assert(!isWriteLockOnCurrentThread());
+
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
HRESULT rc = S_OK;
- /* we access parent medium objects */
- AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
-
/* paranoid sanity checking if the medium has a to-be parent medium */
if (pToBeParent)
{
@@ -3806,8 +3892,7 @@ HRESULT Medium::createMediumLockList(bool fFailIfInaccessible,
ComObjPtr<Medium> pMedium = this;
while (!pMedium.isNull())
{
- // need write lock for RefreshState if medium is inaccessible
- AutoWriteLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
+ AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
/* Accessibility check must be first, otherwise locking interferes
* with getting the medium state. Lock lists are not created for
@@ -3815,9 +3900,12 @@ HRESULT Medium::createMediumLockList(bool fFailIfInaccessible,
MediumState_T mediumState = pMedium->getState();
if (mediumState == MediumState_Inaccessible)
{
- rc = pMedium->RefreshState(&mediumState);
+ alock.release();
+ rc = pMedium->queryInfo(false /* fSetImageId */, false /* fSetParentId */);
+ alock.acquire();
if (FAILED(rc)) return rc;
+ mediumState = pMedium->getState();
if (mediumState == MediumState_Inaccessible)
{
// ignore inaccessible ISO media and silently return S_OK,
@@ -3884,9 +3972,6 @@ HRESULT Medium::createMediumLockList(bool fFailIfInaccessible,
* operation completion.
* @param aWait @c true if this method should block instead of
* creating an asynchronous thread.
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs that will receive the registry IDs that need saving.
- * This only works in "wait" mode; otherwise saveRegistries is called automatically by the thread that
- * was created, and this parameter is ignored.
*
* @note Locks this object and @a aTarget for writing.
*/
@@ -3894,8 +3979,7 @@ HRESULT Medium::createDiffStorage(ComObjPtr<Medium> &aTarget,
MediumVariant_T aVariant,
MediumLockList *aMediumLockList,
ComObjPtr<Progress> *aProgress,
- bool aWait,
- GuidList *pllRegistriesThatNeedSaving)
+ bool aWait)
{
AssertReturn(!aTarget.isNull(), E_FAIL);
AssertReturn(aMediumLockList, E_FAIL);
@@ -3986,7 +4070,7 @@ HRESULT Medium::createDiffStorage(ComObjPtr<Medium> &aTarget,
if (SUCCEEDED(rc))
{
if (aWait)
- rc = runNow(pTask, pllRegistriesThatNeedSaving);
+ rc = runNow(pTask);
else
rc = startThread(pTask);
@@ -4028,13 +4112,11 @@ Utf8Str Medium::getPreferredDiffFormat()
* After this returns with success, uninit() has been called on the medium, and
* the object is no longer usable ("not ready" state).
*
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs that will receive the registry IDs that need saving.
* @param autoCaller AutoCaller instance which must have been created on the caller's stack for this medium. This gets released here
* upon which the Medium instance gets uninitialized.
* @return
*/
-HRESULT Medium::close(GuidList *pllRegistriesThatNeedSaving,
- AutoCaller &autoCaller)
+HRESULT Medium::close(AutoCaller &autoCaller)
{
// we're accessing parent/child and backrefs, so lock the tree first, then ourselves
AutoMultiWriteLock2 multilock(&m->pVirtualBox->getMediaTreeLockHandle(),
@@ -4071,12 +4153,26 @@ HRESULT Medium::close(GuidList *pllRegistriesThatNeedSaving,
// remove from the list of known media before performing actual
// uninitialization (to keep the media registry consistent on
// failure to do so)
- rc = unregisterWithVirtualBox(pllRegistriesThatNeedSaving);
+ rc = unregisterWithVirtualBox();
if (FAILED(rc)) return rc;
- }
- // leave the AutoCaller, as otherwise uninit() will simply hang
- autoCaller.release();
+ multilock.release();
+ markRegistriesModified();
+ // Release the AutoCalleri now, as otherwise uninit() will simply hang.
+ // Needs to be done before saving the registry, as otherwise there
+ // may be a deadlock with someone else closing this object while we're
+ // in saveModifiedRegistries(), which needs the media tree lock, which
+ // the other thread holds until after uninit() below.
+ /// @todo redesign the locking here, as holding the locks over uninit causes lock order trouble which the lock validator can't detect
+ autoCaller.release();
+ m->pVirtualBox->saveModifiedRegistries();
+ multilock.acquire();
+ }
+ else
+ {
+ // release the AutoCaller, as otherwise uninit() will simply hang
+ autoCaller.release();
+ }
// Keep the locks held until after uninit, as otherwise the consistency
// of the medium tree cannot be guaranteed.
@@ -4105,16 +4201,12 @@ HRESULT Medium::close(GuidList *pllRegistriesThatNeedSaving,
* completion.
* @param aWait @c true if this method should block instead of creating
* an asynchronous thread.
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving.
- * This only works in "wait" mode; otherwise saveRegistries gets called automatically by the thread that was created,
- * and this parameter is ignored.
*
* @note Locks mVirtualBox and this object for writing. Locks medium tree for
* writing.
*/
HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress,
- bool aWait,
- GuidList *pllRegistriesThatNeedSaving)
+ bool aWait)
{
AssertReturn(aProgress != NULL || aWait == true, E_FAIL);
@@ -4193,17 +4285,21 @@ HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress,
/* Build the medium lock list. */
MediumLockList *pMediumLockList(new MediumLockList());
+ multilock.release();
rc = createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
NULL,
*pMediumLockList);
+ multilock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
throw rc;
}
+ multilock.release();
rc = pMediumLockList->Lock();
+ multilock.acquire();
if (FAILED(rc))
{
delete pMediumLockList;
@@ -4216,11 +4312,12 @@ HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress,
* actual deletion (we favor the consistency of the media registry
* which would have been broken if unregisterWithVirtualBox() failed
* after we successfully deleted the storage) */
- rc = unregisterWithVirtualBox(pllRegistriesThatNeedSaving);
+ rc = unregisterWithVirtualBox();
if (FAILED(rc))
throw rc;
// no longer need lock
multilock.release();
+ markRegistriesModified();
if (aProgress != NULL)
{
@@ -4252,7 +4349,7 @@ HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress,
if (SUCCEEDED(rc))
{
if (aWait)
- rc = runNow(pTask, NULL /* pllRegistriesThatNeedSaving */);
+ rc = runNow(pTask);
else
rc = startThread(pTask);
@@ -4285,7 +4382,7 @@ HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress,
*/
HRESULT Medium::markForDeletion()
{
- ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
+ ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
switch (m->state)
{
case MediumState_Created:
@@ -4305,7 +4402,7 @@ HRESULT Medium::markForDeletion()
*/
HRESULT Medium::unmarkForDeletion()
{
- ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
+ ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
switch (m->state)
{
case MediumState_Deleting:
@@ -4323,7 +4420,7 @@ HRESULT Medium::unmarkForDeletion()
*/
HRESULT Medium::markLockedForDeletion()
{
- ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
+ ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
if ( ( m->state == MediumState_LockedRead
|| m->state == MediumState_LockedWrite)
&& m->preLockState == MediumState_Created)
@@ -4342,7 +4439,7 @@ HRESULT Medium::markLockedForDeletion()
*/
HRESULT Medium::unmarkLockedForDeletion()
{
- ComAssertRet(this->lockHandle()->isWriteLockOnCurrentThread(), E_FAIL);
+ ComAssertRet(isWriteLockOnCurrentThread(), E_FAIL);
if ( ( m->state == MediumState_LockedRead
|| m->state == MediumState_LockedWrite)
&& m->preLockState == MediumState_Deleting)
@@ -4409,7 +4506,7 @@ HRESULT Medium::prepareMergeTo(const ComObjPtr<Medium> &pTarget,
try
{
// locking: we need the tree lock first because we access parent pointers
- AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
/* more sanity checking and figuring out the merge direction */
ComObjPtr<Medium> pMedium = getParent();
@@ -4441,6 +4538,7 @@ HRESULT Medium::prepareMergeTo(const ComObjPtr<Medium> &pTarget,
/* Build the lock list. */
aMediumLockList = new MediumLockList();
+ treeLock.release();
if (fMergeForward)
rc = pTarget->createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
@@ -4451,6 +4549,7 @@ HRESULT Medium::prepareMergeTo(const ComObjPtr<Medium> &pTarget,
false /* fMediumLockWrite */,
NULL,
*aMediumLockList);
+ treeLock.acquire();
if (FAILED(rc))
throw rc;
@@ -4547,34 +4646,38 @@ HRESULT Medium::prepareMergeTo(const ComObjPtr<Medium> &pTarget,
}
/* Update medium states appropriately */
- if (m->state == MediumState_Created)
{
- rc = markForDeletion();
- if (FAILED(rc))
- throw rc;
- }
- else
- {
- if (fLockMedia)
- throw setStateError();
- else if ( m->state == MediumState_LockedWrite
- || m->state == MediumState_LockedRead)
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (m->state == MediumState_Created)
{
- /* Either mark it for deletion in locked state or allow
- * others to have done so. */
- if (m->preLockState == MediumState_Created)
- markLockedForDeletion();
- else if (m->preLockState != MediumState_Deleting)
- throw setStateError();
+ rc = markForDeletion();
+ if (FAILED(rc))
+ throw rc;
}
else
- throw setStateError();
+ {
+ if (fLockMedia)
+ throw setStateError();
+ else if ( m->state == MediumState_LockedWrite
+ || m->state == MediumState_LockedRead)
+ {
+ /* Either mark it for deletion in locked state or allow
+ * others to have done so. */
+ if (m->preLockState == MediumState_Created)
+ markLockedForDeletion();
+ else if (m->preLockState != MediumState_Deleting)
+ throw setStateError();
+ }
+ else
+ throw setStateError();
+ }
}
if (fMergeForward)
{
/* we will need parent to reparent target */
- pParentForTarget = m->pParent;
+ pParentForTarget = getParent();
}
else
{
@@ -4634,7 +4737,9 @@ HRESULT Medium::prepareMergeTo(const ComObjPtr<Medium> &pTarget,
if (fLockMedia)
{
+ treeLock.release();
rc = aMediumLockList->Lock();
+ treeLock.acquire();
if (FAILED(rc))
{
AutoReadLock alock(pTarget COMMA_LOCKVAL_SRC_POS);
@@ -4727,9 +4832,6 @@ HRESULT Medium::prepareMergeTo(const ComObjPtr<Medium> &pTarget,
* completion.
* @param aWait @c true if this method should block instead of creating
* an asynchronous thread.
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving.
- * This only works in "wait" mode; otherwise saveRegistries gets called automatically by the thread that was created,
- * and this parameter is ignored.
*
* @note Locks the tree lock for writing. Locks the media from the chain
* for writing.
@@ -4740,8 +4842,7 @@ HRESULT Medium::mergeTo(const ComObjPtr<Medium> &pTarget,
const MediaList &aChildrenToReparent,
MediumLockList *aMediumLockList,
ComObjPtr <Progress> *aProgress,
- bool aWait,
- GuidList *pllRegistriesThatNeedSaving)
+ bool aWait)
{
AssertReturn(pTarget != NULL, E_FAIL);
AssertReturn(pTarget != this, E_FAIL);
@@ -4803,7 +4904,7 @@ HRESULT Medium::mergeTo(const ComObjPtr<Medium> &pTarget,
if (SUCCEEDED(rc))
{
if (aWait)
- rc = runNow(pTask, pllRegistriesThatNeedSaving);
+ rc = runNow(pTask);
else
rc = startThread(pTask);
@@ -4877,6 +4978,8 @@ void Medium::cancelMergeTo(const MediaList &aChildrenToReparent,
*/
HRESULT Medium::fixParentUuidOfChildren(const MediaList &childrenToReparent)
{
+ Assert(!isWriteLockOnCurrentThread());
+ Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
MediumLockList mediumLockList;
HRESULT rc = createMediumLockList(true /* fFailIfInaccessible */,
false /* fMediumLockWrite */,
@@ -4971,7 +5074,7 @@ HRESULT Medium::fixParentUuidOfChildren(const MediaList &childrenToReparent)
HRESULT Medium::exportFile(const char *aFilename,
const ComObjPtr<MediumFormat> &aFormat,
MediumVariant_T aVariant,
- void *aVDImageIOCallbacks, void *aVDImageIOUser,
+ PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,
const ComObjPtr<Progress> &aProgress)
{
AssertPtrReturn(aFilename, E_INVALIDARG);
@@ -4986,10 +5089,7 @@ HRESULT Medium::exportFile(const char *aFilename,
try
{
- // locking: we need the tree lock first because we access parent pointers
- AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
- // and we need to write-lock the media involved
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ // This needs no extra locks besides what is done in the called methods.
/* Build the source lock list. */
MediumLockList *pSourceMediumLockList(new MediumLockList());
@@ -5014,7 +5114,7 @@ HRESULT Medium::exportFile(const char *aFilename,
/* setup task object to carry out the operation asynchronously */
pTask = new Medium::ExportTask(this, aProgress, aFilename, aFormat,
- aVariant, aVDImageIOCallbacks,
+ aVariant, aVDImageIOIf,
aVDImageIOUser, pSourceMediumLockList);
rc = pTask->rc();
AssertComRC(rc);
@@ -5049,7 +5149,7 @@ HRESULT Medium::exportFile(const char *aFilename,
HRESULT Medium::importFile(const char *aFilename,
const ComObjPtr<MediumFormat> &aFormat,
MediumVariant_T aVariant,
- void *aVDImageIOCallbacks, void *aVDImageIOUser,
+ PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,
const ComObjPtr<Medium> &aParent,
const ComObjPtr<Progress> &aProgress)
{
@@ -5066,9 +5166,16 @@ HRESULT Medium::importFile(const char *aFilename,
try
{
// locking: we need the tree lock first because we access parent pointers
- AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
// and we need to write-lock the media involved
- AutoMultiWriteLock2 alock(this, aParent COMMA_LOCKVAL_SRC_POS);
+ uint32_t cHandles = 2;
+ LockHandle* pHandles[3] = { &m->pVirtualBox->getMediaTreeLockHandle(),
+ this->lockHandle() };
+ /* Only add parent to the lock if it is not null */
+ if (!aParent.isNull())
+ pHandles[cHandles++] = aParent->lockHandle();
+ AutoWriteLock alock(cHandles,
+ pHandles
+ COMMA_LOCKVAL_SRC_POS);
if ( m->state != MediumState_NotCreated
&& m->state != MediumState_Created)
@@ -5076,17 +5183,21 @@ HRESULT Medium::importFile(const char *aFilename,
/* Build the target lock list. */
MediumLockList *pTargetMediumLockList(new MediumLockList());
+ alock.release();
rc = createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
aParent,
*pTargetMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pTargetMediumLockList;
throw rc;
}
+ alock.release();
rc = pTargetMediumLockList->Lock();
+ alock.acquire();
if (FAILED(rc))
{
delete pTargetMediumLockList;
@@ -5097,7 +5208,7 @@ HRESULT Medium::importFile(const char *aFilename,
/* setup task object to carry out the operation asynchronously */
pTask = new Medium::ImportTask(this, aProgress, aFilename, aFormat,
- aVariant, aVDImageIOCallbacks,
+ aVariant, aVDImageIOIf,
aVDImageIOUser, aParent,
pTargetMediumLockList);
rc = pTask->rc();
@@ -5153,9 +5264,17 @@ HRESULT Medium::cloneToEx(const ComObjPtr<Medium> &aTarget, ULONG aVariant,
try
{
// locking: we need the tree lock first because we access parent pointers
- AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
// and we need to write-lock the media involved
- AutoMultiWriteLock3 alock(this, aTarget, aParent COMMA_LOCKVAL_SRC_POS);
+ uint32_t cHandles = 3;
+ LockHandle* pHandles[4] = { &m->pVirtualBox->getMediaTreeLockHandle(),
+ this->lockHandle(),
+ aTarget->lockHandle() };
+ /* Only add parent to the lock if it is not null */
+ if (!aParent.isNull())
+ pHandles[cHandles++] = aParent->lockHandle();
+ AutoWriteLock alock(cHandles,
+ pHandles
+ COMMA_LOCKVAL_SRC_POS);
if ( aTarget->m->state != MediumState_NotCreated
&& aTarget->m->state != MediumState_Created)
@@ -5163,10 +5282,12 @@ HRESULT Medium::cloneToEx(const ComObjPtr<Medium> &aTarget, ULONG aVariant,
/* Build the source lock list. */
MediumLockList *pSourceMediumLockList(new MediumLockList());
+ alock.release();
rc = createMediumLockList(true /* fFailIfInaccessible */,
false /* fMediumLockWrite */,
NULL,
*pSourceMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pSourceMediumLockList;
@@ -5175,10 +5296,12 @@ HRESULT Medium::cloneToEx(const ComObjPtr<Medium> &aTarget, ULONG aVariant,
/* Build the target lock list (including the to-be parent chain). */
MediumLockList *pTargetMediumLockList(new MediumLockList());
+ alock.release();
rc = aTarget->createMediumLockList(true /* fFailIfInaccessible */,
true /* fMediumLockWrite */,
aParent,
*pTargetMediumLockList);
+ alock.acquire();
if (FAILED(rc))
{
delete pSourceMediumLockList;
@@ -5186,7 +5309,9 @@ HRESULT Medium::cloneToEx(const ComObjPtr<Medium> &aTarget, ULONG aVariant,
throw rc;
}
+ alock.release();
rc = pSourceMediumLockList->Lock();
+ alock.acquire();
if (FAILED(rc))
{
delete pSourceMediumLockList;
@@ -5195,7 +5320,9 @@ HRESULT Medium::cloneToEx(const ComObjPtr<Medium> &aTarget, ULONG aVariant,
tr("Failed to lock source media '%s'"),
getLocationFull().c_str());
}
+ alock.release();
rc = pTargetMediumLockList->Lock();
+ alock.acquire();
if (FAILED(rc))
{
delete pSourceMediumLockList;
@@ -5261,9 +5388,9 @@ HRESULT Medium::cloneToEx(const ComObjPtr<Medium> &aTarget, ULONG aVariant,
* @note This method may block during a system I/O call that checks storage
* accessibility.
*
- * @note Locks medium tree for reading and writing (for new diff media checked
- * for the first time). Locks mParent for reading. Locks this object for
- * writing.
+ * @note Caller MUST NOT hold the media tree or medium lock.
+ *
+ * @note Locks mParent for reading. Locks this object for writing.
*
* @param fSetImageId Whether to reset the UUID contained in the image file to the UUID in the medium instance data (see SetIDs())
* @param fSetParentId Whether to reset the parent UUID contained in the image file to the parent UUID in the medium instance data (see SetIDs())
@@ -5271,6 +5398,7 @@ HRESULT Medium::cloneToEx(const ComObjPtr<Medium> &aTarget, ULONG aVariant,
*/
HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
{
+ Assert(!isWriteLockOnCurrentThread());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
if ( m->state != MediumState_Created
@@ -5289,11 +5417,14 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
Assert( m->state == MediumState_LockedRead
|| m->state == MediumState_LockedWrite);
- alock.leave();
- vrc = RTSemEventMultiWait(m->queryInfoSem, RT_INDEFINITE_WAIT);
- alock.enter();
-
- AssertRC(vrc);
+ while (m->queryInfoRunning)
+ {
+ alock.release();
+ {
+ AutoReadLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
+ }
+ alock.acquire();
+ }
return S_OK;
}
@@ -5322,11 +5453,13 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
uOpenFlags |= VD_OPEN_FLAGS_SHAREABLE;
/* Lock the medium, which makes the behavior much more consistent */
+ alock.release();
if (uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE))
rc = LockRead(NULL);
else
rc = LockWrite(NULL);
if (FAILED(rc)) return rc;
+ alock.acquire();
/* Copies of the input state fields which are not read-only,
* as we're dropping the lock. CAUTION: be extremely careful what
@@ -5346,11 +5479,21 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
* need repairing after it was closed again. */
bool fRepairImageZeroParentUuid = false;
- /* leave the lock before a lengthy operation */
- vrc = RTSemEventMultiReset(m->queryInfoSem);
- AssertRCReturn(vrc, E_FAIL);
+ /* release the object lock before a lengthy operation, and take the
+ * opportunity to have a media tree lock, too, which isn't held initially */
m->queryInfoRunning = true;
- alock.leave();
+ alock.release();
+ Assert(!isWriteLockOnCurrentThread());
+ Assert(!m->pVirtualBox->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
+ AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
+ treeLock.release();
+
+ /* Note that taking the queryInfoSem after leaving the object lock above
+ * can lead to short spinning of the loops waiting for queryInfo() to
+ * complete. This is unavoidable since the other order causes a lock order
+ * violation: here it would be requesting the object lock (at the beginning
+ * of the method), then queryInfoSem, and below the other way round. */
+ AutoWriteLock qlock(m->queryInfoSem COMMA_LOCKVAL_SRC_POS);
try
{
@@ -5388,18 +5531,24 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
* not modified by other code, so no need to copy. */
if (fSetImageId)
{
+ alock.acquire();
vrc = VDSetUuid(hdd, 0, m->uuidImage.raw());
+ alock.release();
ComAssertRCThrow(vrc, E_FAIL);
mediumId = m->uuidImage;
}
if (fSetParentId)
{
+ alock.acquire();
vrc = VDSetParentUuid(hdd, 0, m->uuidParentImage.raw());
+ alock.release();
ComAssertRCThrow(vrc, E_FAIL);
}
/* zap the information, these are no long-term members */
+ alock.acquire();
unconst(m->uuidImage).clear();
unconst(m->uuidParentImage).clear();
+ alock.release();
/* check the UUID */
RTUUID uuid;
@@ -5439,7 +5588,9 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
if (fSetImageId)
{
/* set the UUID if an API client wants to change it */
+ alock.acquire();
mediumId = m->uuidImage;
+ alock.release();
}
else if (isImport)
{
@@ -5448,11 +5599,21 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
}
}
+ /* set the image uuid before the below parent uuid handling code
+ * might place it somewhere in the media tree, so that the medium
+ * UUID is valid at this point */
+ alock.acquire();
+ if (isImport || fSetImageId)
+ unconst(m->id) = mediumId;
+ alock.release();
+
/* get the medium variant */
unsigned uImageFlags;
vrc = VDGetImageFlags(hdd, 0, &uImageFlags);
ComAssertRCThrow(vrc, E_FAIL);
+ alock.acquire();
m->variant = (MediumVariant_T)uImageFlags;
+ alock.release();
/* check/get the parent uuid and update corresponding state */
if (uImageFlags & VD_IMAGE_FLAGS_DIFF)
@@ -5466,7 +5627,7 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
* Since such images don't support random writes they will not
* be created for diff images. Only an overly smart user might
* manually create this case. Too bad for him. */
- if ( isImport
+ if ( (isImport || fSetParentId)
&& !(uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED))
{
/* the parent must be known to us. Note that we freely
@@ -5476,29 +5637,50 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
* threads yet (and init() will fail if this method reports
* MediumState_Inaccessible) */
- Guid id = parentId;
ComObjPtr<Medium> pParent;
- rc = m->pVirtualBox->findHardDiskById(id, false /* aSetError */, &pParent);
+ if (RTUuidIsNull(&parentId))
+ rc = VBOX_E_OBJECT_NOT_FOUND;
+ else
+ rc = m->pVirtualBox->findHardDiskById(Guid(parentId), false /* aSetError */, &pParent);
if (FAILED(rc))
{
- lastAccessError = Utf8StrFmt(
- tr("Parent medium with UUID {%RTuuid} of the medium '%s' is not found in the media registry ('%s')"),
- &parentId, location.c_str(),
- m->pVirtualBox->settingsFilePath().c_str());
- throw S_OK;
+ if (fSetImageId && !fSetParentId)
+ {
+ /* If the image UUID gets changed for an existing
+ * image then the parent UUID can be stale. In such
+ * cases clear the parent information. The parent
+ * information may/will be re-set later if the
+ * API client wants to adjust a complete medium
+ * hierarchy one by one. */
+ rc = S_OK;
+ alock.acquire();
+ RTUuidClear(&parentId);
+ vrc = VDSetParentUuid(hdd, 0, &parentId);
+ alock.release();
+ ComAssertRCThrow(vrc, E_FAIL);
+ }
+ else
+ {
+ lastAccessError = Utf8StrFmt(tr("Parent medium with UUID {%RTuuid} of the medium '%s' is not found in the media registry ('%s')"),
+ &parentId, location.c_str(),
+ m->pVirtualBox->settingsFilePath().c_str());
+ throw S_OK;
+ }
}
/* we set mParent & children() */
- AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
+ treeLock.acquire();
- Assert(m->pParent.isNull());
- m->pParent = pParent;
- m->pParent->m->llChildren.push_back(this);
+ if (m->pParent)
+ deparent();
+ setParent(pParent);
+
+ treeLock.release();
}
else
{
/* we access mParent */
- AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
+ treeLock.acquire();
/* check that parent UUIDs match. Note that there's no need
* for the parent's AutoCaller (our lifetime is bound to
@@ -5521,27 +5703,34 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
tr("Medium type of '%s' is differencing but it is not associated with any parent medium in the media registry ('%s')"),
location.c_str(),
m->pVirtualBox->settingsFilePath().c_str());
+ treeLock.release();
throw S_OK;
#endif /* 0 */
}
- AutoReadLock parentLock(m->pParent COMMA_LOCKVAL_SRC_POS);
- if ( !fRepairImageZeroParentUuid
- && m->pParent->getState() != MediumState_Inaccessible
- && m->pParent->getId() != parentId)
{
- /** @todo r=klaus this always refers to VirtualBox.xml as the medium registry, even for new VMs */
- lastAccessError = Utf8StrFmt(
- tr("Parent UUID {%RTuuid} of the medium '%s' does not match UUID {%RTuuid} of its parent medium stored in the media registry ('%s')"),
- &parentId, location.c_str(),
- m->pParent->getId().raw(),
- m->pVirtualBox->settingsFilePath().c_str());
- throw S_OK;
+ AutoReadLock parentLock(m->pParent COMMA_LOCKVAL_SRC_POS);
+ if ( !fRepairImageZeroParentUuid
+ && m->pParent->getState() != MediumState_Inaccessible
+ && m->pParent->getId() != parentId)
+ {
+ /** @todo r=klaus this always refers to VirtualBox.xml as the medium registry, even for new VMs */
+ lastAccessError = Utf8StrFmt(
+ tr("Parent UUID {%RTuuid} of the medium '%s' does not match UUID {%RTuuid} of its parent medium stored in the media registry ('%s')"),
+ &parentId, location.c_str(),
+ m->pParent->getId().raw(),
+ m->pVirtualBox->settingsFilePath().c_str());
+ parentLock.release();
+ treeLock.release();
+ throw S_OK;
+ }
}
/// @todo NEWMEDIA what to do if the parent is not
/// accessible while the diff is? Probably nothing. The
/// real code will detect the mismatch anyway.
+
+ treeLock.release();
}
}
@@ -5555,17 +5744,22 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
rc = aRC;
}
- VDDestroy(hdd);
+ vrc = VDDestroy(hdd);
+ if (RT_FAILURE(vrc))
+ {
+ lastAccessError = Utf8StrFmt(tr("Could not update and close the medium '%s'%s"),
+ location.c_str(), vdError(vrc).c_str());
+ success = false;
+ throw S_OK;
+ }
}
catch (HRESULT aRC)
{
rc = aRC;
}
- alock.enter();
-
- if (isImport || fSetImageId)
- unconst(m->id) = mediumId;
+ treeLock.acquire();
+ alock.acquire();
if (success)
{
@@ -5581,8 +5775,8 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
rc, vrc));
}
- /* inform other callers if there are any */
- RTSemEventMultiSignal(m->queryInfoSem);
+ /* unblock anyone waiting for the queryInfo results */
+ qlock.release();
m->queryInfoRunning = false;
/* Set the proper state according to the result of the check */
@@ -5611,7 +5805,7 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
rc = LockWrite(NULL);
if (FAILED(rc)) return rc;
- alock.leave();
+ alock.release();
try
{
@@ -5646,8 +5840,6 @@ HRESULT Medium::queryInfo(bool fSetImageId, bool fSetParentId)
rc = aRC;
}
- alock.enter();
-
rc = UnlockWrite(NULL);
if (SUCCEEDED(rc) && FAILED(rc2))
rc = rc2;
@@ -5681,11 +5873,9 @@ HRESULT Medium::canClose()
/**
* Unregisters this medium with mVirtualBox. Called by close() under the medium tree lock.
*
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs that will receive the registry IDs that need saving.
- *
* @note Caller must have locked the media tree lock for writing!
*/
-HRESULT Medium::unregisterWithVirtualBox(GuidList *pllRegistriesThatNeedSaving)
+HRESULT Medium::unregisterWithVirtualBox()
{
/* Note that we need to de-associate ourselves from the parent to let
* unregisterMedium() properly save the registry */
@@ -5698,7 +5888,7 @@ HRESULT Medium::unregisterWithVirtualBox(GuidList *pllRegistriesThatNeedSaving)
if (m->pParent)
deparent();
- HRESULT rc = m->pVirtualBox->unregisterMedium(this, pllRegistriesThatNeedSaving);
+ HRESULT rc = m->pVirtualBox->unregisterMedium(this);
if (FAILED(rc))
{
if (pParentBackup)
@@ -5713,6 +5903,30 @@ HRESULT Medium::unregisterWithVirtualBox(GuidList *pllRegistriesThatNeedSaving)
}
/**
+ * Like SetProperty but do not trigger a settings store. Only for internal use!
+ */
+HRESULT Medium::setPropertyDirect(const Utf8Str &aName, const Utf8Str &aValue)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock mlock(this COMMA_LOCKVAL_SRC_POS);
+
+ switch (m->state)
+ {
+ case MediumState_Created:
+ case MediumState_Inaccessible:
+ break;
+ default:
+ return setStateError();
+ }
+
+ m->mapProperties[aName] = aValue;
+
+ return S_OK;
+}
+
+/**
* Sets the extended error info according to the current media state.
*
* @note Must be called from under this object's write or read lock.
@@ -5893,7 +6107,8 @@ HRESULT Medium::setLocation(const Utf8Str &aLocation,
}
else if ( vrc != VERR_FILE_NOT_FOUND
&& vrc != VERR_PATH_NOT_FOUND
- && vrc != VERR_ACCESS_DENIED)
+ && vrc != VERR_ACCESS_DENIED
+ && locationFull != aLocation)
{
/* assume it's not a file, restore the original location */
locationFull = aLocation;
@@ -6337,8 +6552,7 @@ HRESULT Medium::startThread(Medium::Task *pTask)
* by this method directly and it's the caller's responsibility to
* complete the progress object in this case.
*/
-HRESULT Medium::runNow(Medium::Task *pTask,
- GuidList *pllRegistriesThatNeedSaving)
+HRESULT Medium::runNow(Medium::Task *pTask)
{
#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
/* Extreme paranoia: The calling thread should not hold the medium
@@ -6348,8 +6562,6 @@ HRESULT Medium::runNow(Medium::Task *pTask,
Assert(!AutoLockHoldsLocksInClass(getLockingClass()));
#endif
- pTask->m_pllRegistriesThatNeedSaving = pllRegistriesThatNeedSaving;
-
/* NIL_RTTHREAD indicates synchronous call. */
return (HRESULT)Medium::Task::fntMediumTask(NIL_RTTHREAD, pTask);
}
@@ -6451,11 +6663,11 @@ HRESULT Medium::taskCreateBaseHandler(Medium::CreateBaseTask &task)
* better than breaking media registry consistency) */
AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
ComObjPtr<Medium> pMedium;
- rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */);
+ rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk);
Assert(this == pMedium);
}
- // reenter the lock before changing state
+ // re-acquire the lock before changing state
AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
if (SUCCEEDED(rc))
@@ -6465,6 +6677,14 @@ HRESULT Medium::taskCreateBaseHandler(Medium::CreateBaseTask &task)
m->size = size;
m->logicalSize = logicalSize;
m->variant = variant;
+
+ thisLock.release();
+ markRegistriesModified();
+ if (task.isAsync())
+ {
+ // in asynchronous mode, save settings now
+ m->pVirtualBox->saveModifiedRegistries();
+ }
}
else
{
@@ -6484,8 +6704,8 @@ HRESULT Medium::taskCreateBaseHandler(Medium::CreateBaseTask &task)
*
* This task always gets started from Medium::createDiffStorage() and can run
* synchronously or asynchronously depending on the "wait" parameter passed to
- * that function. If we run synchronously, the caller expects the GuidList
- * *pllRegistriesThatNeedSaving to be set before returning; otherwise (in asynchronous
+ * that function. If we run synchronously, the caller expects the medium
+ * registry modification to be set before returning; otherwise (in asynchronous
* mode), we save the settings ourselves.
*
* @param task
@@ -6501,8 +6721,6 @@ HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task)
MediumVariant_T variant = MediumVariant_Standard;
bool fGenerateUuid = false;
- GuidList llRegistriesThatNeedSaving; // gets copied to task pointer later in synchronous mode
-
try
{
/* Lock both in {parent,child} order. */
@@ -6630,7 +6848,7 @@ HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task)
* Created state only on success (leaving an orphan file is
* better than breaking media registry consistency) */
ComObjPtr<Medium> pMedium;
- mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium, DeviceType_HardDisk, &llRegistriesThatNeedSaving);
+ mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium, DeviceType_HardDisk);
Assert(pTarget == pMedium);
if (FAILED(mrc))
@@ -6664,15 +6882,13 @@ HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task)
Assert(m->numCreateDiffTasks != 0);
--m->numCreateDiffTasks;
+ mediaLock.release();
+ markRegistriesModified();
if (task.isAsync())
{
- mediaLock.release();
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ // in asynchronous mode, save settings now
+ m->pVirtualBox->saveModifiedRegistries();
}
- else
- // synchronous mode: report save settings result to caller
- if (task.m_pllRegistriesThatNeedSaving)
- *task.m_pllRegistriesThatNeedSaving = llRegistriesThatNeedSaving;
/* Note that in sync mode, it's the caller's responsibility to
* unlock the medium. */
@@ -6685,8 +6901,8 @@ HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task)
*
* This task always gets started from Medium::mergeTo() and can run
* synchronously or asynchronously depending on the "wait" parameter passed to
- * that function. If we run synchronously, the caller expects the GuidList
- * *pllRegistriesThatNeedSaving to be set before returning; otherwise (in asynchronous
+ * that function. If we run synchronously, the caller expects the medium
+ * registry modification to be set before returning; otherwise (in asynchronous
* mode), we save the settings ourselves.
*
* @param task
@@ -6850,7 +7066,7 @@ HRESULT Medium::taskMergeHandler(Medium::MergeTask &task)
{
/* first, unregister the target since it may become a base
* medium which needs re-registration */
- rc2 = m->pVirtualBox->unregisterMedium(pTarget, NULL /* pllRegistriesThatNeedSaving */);
+ rc2 = m->pVirtualBox->unregisterMedium(pTarget);
AssertComRC(rc2);
/* then, reparent it and disconnect the deleted branch at
@@ -6865,8 +7081,8 @@ HRESULT Medium::taskMergeHandler(Medium::MergeTask &task)
/* then, register again */
ComObjPtr<Medium> pMedium;
- rc2 = m->pVirtualBox->registerMedium(pTarget, &pMedium, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */ );
- Assert(pTarget == pMedium);
+ rc2 = m->pVirtualBox->registerMedium(pTarget, &pMedium,
+ DeviceType_HardDisk);
AssertComRC(rc2);
}
else
@@ -6919,7 +7135,7 @@ HRESULT Medium::taskMergeHandler(Medium::MergeTask &task)
continue;
}
- rc2 = pMedium->m->pVirtualBox->unregisterMedium(pMedium, NULL /* pllRegistriesThatNeedSaving */);
+ rc2 = pMedium->m->pVirtualBox->unregisterMedium(pMedium);
AssertComRC(rc2);
/* now, uninitialize the deleted medium (note that
@@ -6952,20 +7168,14 @@ HRESULT Medium::taskMergeHandler(Medium::MergeTask &task)
}
}
+ markRegistriesModified();
if (task.isAsync())
{
// in asynchronous mode, save settings now
- GuidList llRegistriesThatNeedSaving;
- addToRegistryIDList(llRegistriesThatNeedSaving);
- /* collect multiple errors */
eik.restore();
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ m->pVirtualBox->saveModifiedRegistries();
eik.fetch();
}
- else
- // synchronous mode: report save settings result to caller
- if (task.m_pllRegistriesThatNeedSaving)
- pTarget->addToRegistryIDList(*task.m_pllRegistriesThatNeedSaving);
if (FAILED(mrc))
{
@@ -7215,7 +7425,8 @@ HRESULT Medium::taskCloneHandler(Medium::CloneTask &task)
* better than breaking media registry consistency) */
eik.restore();
ComObjPtr<Medium> pMedium;
- mrc = pParent->m->pVirtualBox->registerMedium(pTarget, &pMedium, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */);
+ mrc = pParent->m->pVirtualBox->registerMedium(pTarget, &pMedium,
+ DeviceType_HardDisk);
Assert(pTarget == pMedium);
eik.fetch();
@@ -7228,7 +7439,8 @@ HRESULT Medium::taskCloneHandler(Medium::CloneTask &task)
/* just register */
eik.restore();
ComObjPtr<Medium> pMedium;
- mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */);
+ mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium,
+ DeviceType_HardDisk);
Assert(pTarget == pMedium);
eik.fetch();
}
@@ -7261,11 +7473,10 @@ HRESULT Medium::taskCloneHandler(Medium::CloneTask &task)
if (SUCCEEDED(mrc))
{
// save the settings
- GuidList llRegistriesThatNeedSaving;
- addToRegistryIDList(llRegistriesThatNeedSaving);
+ markRegistriesModified();
/* collect multiple errors */
eik.restore();
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ m->pVirtualBox->saveModifiedRegistries();
eik.fetch();
}
@@ -7664,15 +7875,15 @@ HRESULT Medium::taskResizeHandler(Medium::ResizeTask &task)
{
if (vrc == VERR_NOT_SUPPORTED)
throw setError(VBOX_E_NOT_SUPPORTED,
- tr("Compacting is not yet supported for medium '%s'"),
- location.c_str());
+ tr("Resizing to new size %llu is not yet supported for medium '%s'"),
+ task.mSize, location.c_str());
else if (vrc == VERR_NOT_IMPLEMENTED)
throw setError(E_NOTIMPL,
- tr("Compacting is not implemented, medium '%s'"),
+ tr("Resiting is not implemented, medium '%s'"),
location.c_str());
else
throw setError(VBOX_E_FILE_ERROR,
- tr("Could not compact medium '%s'%s"),
+ tr("Could not resize medium '%s'%s"),
location.c_str(),
vdError(vrc).c_str());
}
@@ -7994,7 +8205,8 @@ HRESULT Medium::taskImportHandler(Medium::ImportTask &task)
* better than breaking media registry consistency) */
eik.restore();
ComObjPtr<Medium> pMedium;
- mrc = pParent->m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk, NULL /* llRegistriesThatNeedSaving */);
+ mrc = pParent->m->pVirtualBox->registerMedium(this, &pMedium,
+ DeviceType_HardDisk);
Assert(this == pMedium);
eik.fetch();
@@ -8007,7 +8219,7 @@ HRESULT Medium::taskImportHandler(Medium::ImportTask &task)
/* just register */
eik.restore();
ComObjPtr<Medium> pMedium;
- mrc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */);
+ mrc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk);
Assert(this == pMedium);
eik.fetch();
}
@@ -8039,11 +8251,10 @@ HRESULT Medium::taskImportHandler(Medium::ImportTask &task)
// now, at the end of this task (always asynchronous), save the settings
{
// save the settings
- GuidList llRegistriesThatNeedSaving;
- addToRegistryIDList(llRegistriesThatNeedSaving);
+ markRegistriesModified();
/* collect multiple errors */
eik.restore();
- m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
+ m->pVirtualBox->saveModifiedRegistries();
eik.fetch();
}
diff --git a/src/VBox/Main/src-server/NATEngineImpl.cpp b/src/VBox/Main/src-server/NATEngineImpl.cpp
index a693b8c17..7ce08fd87 100644
--- a/src/VBox/Main/src-server/NATEngineImpl.cpp
+++ b/src/VBox/Main/src-server/NATEngineImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -59,7 +59,7 @@ HRESULT NATEngine::init(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *
AssertReturn(autoInitSpan.isOk(), E_FAIL);
Log(("init that:%p this:%p\n", aThat, this));
- AutoCaller thatCaller (aThat);
+ AutoCaller thatCaller(aThat);
AssertComRCReturnRC(thatCaller.rc());
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
@@ -78,14 +78,14 @@ HRESULT NATEngine::init(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *
return S_OK;
}
-HRESULT NATEngine::initCopy (Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat)
+HRESULT NATEngine::initCopy(Machine *aParent, INetworkAdapter *aAdapter, NATEngine *aThat)
{
AutoInitSpan autoInitSpan(this);
AssertReturn(autoInitSpan.isOk(), E_FAIL);
Log(("initCopy that:%p this:%p\n", aThat, this));
- AutoCaller thatCaller (aThat);
+ AutoCaller thatCaller(aThat);
AssertComRCReturnRC(thatCaller.rc());
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
@@ -132,7 +132,7 @@ bool NATEngine::isModified()
bool NATEngine::rollback()
{
AutoCaller autoCaller(this);
- AssertComRCReturn (autoCaller.rc(), false);
+ AssertComRCReturn(autoCaller.rc(), false);
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
bool fChanged = m_fModified;
@@ -150,11 +150,11 @@ bool NATEngine::rollback()
void NATEngine::commit()
{
AutoCaller autoCaller(this);
- AssertComRCReturnVoid (autoCaller.rc());
+ AssertComRCReturnVoid(autoCaller.rc());
/* sanity too */
- AutoCaller peerCaller (mPeer);
- AssertComRCReturnVoid (peerCaller.rc());
+ AutoCaller peerCaller(mPeer);
+ AssertComRCReturnVoid(peerCaller.rc());
/* lock both for writing since we modify both (mPeer is "master" so locked
* first) */
@@ -164,7 +164,7 @@ void NATEngine::commit()
mData.commit();
if (mPeer)
{
- mPeer->mData.attach (mData);
+ mPeer->mData.attach(mData);
mPeer->mNATRules.clear();
NATRuleMap::iterator it;
for (it = mNATRules.begin(); it != mNATRules.end(); ++it)
@@ -357,13 +357,13 @@ HRESULT NATEngine::loadSettings(const settings::NAT &data)
mData->mTcpRcv = data.u32TcpRcv;
mData->mTcpSnd = data.u32TcpSnd;
/* TFTP */
- mData->mTftpPrefix = data.strTftpPrefix;
- mData->mTftpBootFile = data.strTftpBootFile;
- mData->mTftpNextServer = data.strTftpNextServer;
+ mData->mTFTPPrefix = data.strTFTPPrefix;
+ mData->mTFTPBootFile = data.strTFTPBootFile;
+ mData->mTFTPNextServer = data.strTFTPNextServer;
/* DNS */
- mData->mDnsPassDomain = data.fDnsPassDomain;
- mData->mDnsProxy = data.fDnsProxy;
- mData->mDnsUseHostResolver = data.fDnsUseHostResolver;
+ mData->mDNSPassDomain = data.fDNSPassDomain;
+ mData->mDNSProxy = data.fDNSProxy;
+ mData->mDNSUseHostResolver = data.fDNSUseHostResolver;
/* Alias */
mData->mAliasMode = (data.fAliasUseSamePorts ? NATAliasMode_AliasUseSamePorts : 0);
mData->mAliasMode |= (data.fAliasLog ? NATAliasMode_AliasLog : 0);
@@ -395,13 +395,13 @@ HRESULT NATEngine::saveSettings(settings::NAT &data)
data.u32TcpRcv = mData->mTcpRcv;
data.u32TcpSnd = mData->mTcpSnd;
/* TFTP */
- data.strTftpPrefix = mData->mTftpPrefix;
- data.strTftpBootFile = mData->mTftpBootFile;
- data.strTftpNextServer = mData->mTftpNextServer;
+ data.strTFTPPrefix = mData->mTFTPPrefix;
+ data.strTFTPBootFile = mData->mTFTPBootFile;
+ data.strTFTPNextServer = mData->mTFTPNextServer;
/* DNS */
- data.fDnsPassDomain = !!mData->mDnsPassDomain;
- data.fDnsProxy = !!mData->mDnsProxy;
- data.fDnsUseHostResolver = !!mData->mDnsUseHostResolver;
+ data.fDNSPassDomain = !!mData->mDNSPassDomain;
+ data.fDNSProxy = !!mData->mDNSProxy;
+ data.fDNSUseHostResolver = !!mData->mDNSUseHostResolver;
/* Alias */
data.fAliasLog = !!(mData->mAliasMode & NATAliasMode_AliasLog);
data.fAliasProxyOnly = !!(mData->mAliasMode & NATAliasMode_AliasProxyOnly);
@@ -419,7 +419,7 @@ STDMETHODIMP
NATEngine::COMSETTER(Network)(IN_BSTR aNetwork)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
if (Bstr(mData->mNetwork) != aNetwork)
{
@@ -448,10 +448,10 @@ NATEngine::COMGETTER(Network)(BSTR *aNetwork)
}
STDMETHODIMP
-NATEngine::COMSETTER(HostIP) (IN_BSTR aBindIP)
+NATEngine::COMSETTER(HostIP)(IN_BSTR aBindIP)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
if (Bstr(mData->mBindIP) != aBindIP)
{
@@ -462,7 +462,7 @@ NATEngine::COMSETTER(HostIP) (IN_BSTR aBindIP)
}
return S_OK;
}
-STDMETHODIMP NATEngine::COMGETTER(HostIP) (BSTR *aBindIP)
+STDMETHODIMP NATEngine::COMGETTER(HostIP)(BSTR *aBindIP)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
@@ -475,15 +475,15 @@ STDMETHODIMP NATEngine::COMGETTER(HostIP) (BSTR *aBindIP)
STDMETHODIMP
-NATEngine::COMSETTER(TftpPrefix)(IN_BSTR aTftpPrefix)
+NATEngine::COMSETTER(TFTPPrefix)(IN_BSTR aTFTPPrefix)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (Bstr(mData->mTftpPrefix) != aTftpPrefix)
+ if (Bstr(mData->mTFTPPrefix) != aTFTPPrefix)
{
mData.backup();
- mData->mTftpPrefix = aTftpPrefix;
+ mData->mTFTPPrefix = aTFTPPrefix;
mParent->setModified(Machine::IsModified_NetworkAdapters);
m_fModified = true;
}
@@ -491,30 +491,30 @@ NATEngine::COMSETTER(TftpPrefix)(IN_BSTR aTftpPrefix)
}
STDMETHODIMP
-NATEngine::COMGETTER(TftpPrefix)(BSTR *aTftpPrefix)
+NATEngine::COMGETTER(TFTPPrefix)(BSTR *aTFTPPrefix)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (!mData->mTftpPrefix.isEmpty())
+ if (!mData->mTFTPPrefix.isEmpty())
{
- mData->mTftpPrefix.cloneTo(aTftpPrefix);
- Log(("Getter (this:%p) TftpPrefix: %s\n", this, mData->mTftpPrefix.c_str()));
+ mData->mTFTPPrefix.cloneTo(aTFTPPrefix);
+ Log(("Getter (this:%p) TFTPPrefix: %s\n", this, mData->mTFTPPrefix.c_str()));
}
return S_OK;
}
STDMETHODIMP
-NATEngine::COMSETTER(TftpBootFile)(IN_BSTR aTftpBootFile)
+NATEngine::COMSETTER(TFTPBootFile)(IN_BSTR aTFTPBootFile)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (Bstr(mData->mTftpBootFile) != aTftpBootFile)
+ if (Bstr(mData->mTFTPBootFile) != aTFTPBootFile)
{
mData.backup();
- mData->mTftpBootFile = aTftpBootFile;
+ mData->mTFTPBootFile = aTFTPBootFile;
mParent->setModified(Machine::IsModified_NetworkAdapters);
m_fModified = true;
}
@@ -522,30 +522,30 @@ NATEngine::COMSETTER(TftpBootFile)(IN_BSTR aTftpBootFile)
}
STDMETHODIMP
-NATEngine::COMGETTER(TftpBootFile)(BSTR *aTftpBootFile)
+NATEngine::COMGETTER(TFTPBootFile)(BSTR *aTFTPBootFile)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (!mData->mTftpBootFile.isEmpty())
+ if (!mData->mTFTPBootFile.isEmpty())
{
- mData->mTftpBootFile.cloneTo(aTftpBootFile);
- Log(("Getter (this:%p) BootFile: %s\n", this, mData->mTftpBootFile.c_str()));
+ mData->mTFTPBootFile.cloneTo(aTFTPBootFile);
+ Log(("Getter (this:%p) BootFile: %s\n", this, mData->mTFTPBootFile.c_str()));
}
return S_OK;
}
STDMETHODIMP
-NATEngine::COMSETTER(TftpNextServer)(IN_BSTR aTftpNextServer)
+NATEngine::COMSETTER(TFTPNextServer)(IN_BSTR aTFTPNextServer)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (Bstr(mData->mTftpNextServer) != aTftpNextServer)
+ if (Bstr(mData->mTFTPNextServer) != aTFTPNextServer)
{
mData.backup();
- mData->mTftpNextServer = aTftpNextServer;
+ mData->mTFTPNextServer = aTFTPNextServer;
mParent->setModified(Machine::IsModified_NetworkAdapters);
m_fModified = true;
}
@@ -553,100 +553,100 @@ NATEngine::COMSETTER(TftpNextServer)(IN_BSTR aTftpNextServer)
}
STDMETHODIMP
-NATEngine::COMGETTER(TftpNextServer)(BSTR *aTftpNextServer)
+NATEngine::COMGETTER(TFTPNextServer)(BSTR *aTFTPNextServer)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (!mData->mTftpNextServer.isEmpty())
+ if (!mData->mTFTPNextServer.isEmpty())
{
- mData->mTftpNextServer.cloneTo(aTftpNextServer);
- Log(("Getter (this:%p) NextServer: %s\n", this, mData->mTftpNextServer.c_str()));
+ mData->mTFTPNextServer.cloneTo(aTFTPNextServer);
+ Log(("Getter (this:%p) NextServer: %s\n", this, mData->mTFTPNextServer.c_str()));
}
return S_OK;
}
/* DNS */
STDMETHODIMP
-NATEngine::COMSETTER(DnsPassDomain) (BOOL aDnsPassDomain)
+NATEngine::COMSETTER(DNSPassDomain) (BOOL aDNSPassDomain)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (mData->mDnsPassDomain != aDnsPassDomain)
+ if (mData->mDNSPassDomain != aDNSPassDomain)
{
mData.backup();
- mData->mDnsPassDomain = aDnsPassDomain;
+ mData->mDNSPassDomain = aDNSPassDomain;
mParent->setModified(Machine::IsModified_NetworkAdapters);
m_fModified = true;
}
return S_OK;
}
STDMETHODIMP
-NATEngine::COMGETTER(DnsPassDomain)(BOOL *aDnsPassDomain)
+NATEngine::COMGETTER(DNSPassDomain)(BOOL *aDNSPassDomain)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aDnsPassDomain = mData->mDnsPassDomain;
+ *aDNSPassDomain = mData->mDNSPassDomain;
return S_OK;
}
STDMETHODIMP
-NATEngine::COMSETTER(DnsProxy)(BOOL aDnsProxy)
+NATEngine::COMSETTER(DNSProxy)(BOOL aDNSProxy)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (mData->mDnsProxy != aDnsProxy)
+ if (mData->mDNSProxy != aDNSProxy)
{
mData.backup();
- mData->mDnsProxy = aDnsProxy;
+ mData->mDNSProxy = aDNSProxy;
mParent->setModified(Machine::IsModified_NetworkAdapters);
m_fModified = true;
}
return S_OK;
}
STDMETHODIMP
-NATEngine::COMGETTER(DnsProxy)(BOOL *aDnsProxy)
+NATEngine::COMGETTER(DNSProxy)(BOOL *aDNSProxy)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aDnsProxy = mData->mDnsProxy;
+ *aDNSProxy = mData->mDNSProxy;
return S_OK;
}
STDMETHODIMP
-NATEngine::COMGETTER(DnsUseHostResolver)(BOOL *aDnsUseHostResolver)
+NATEngine::COMGETTER(DNSUseHostResolver)(BOOL *aDNSUseHostResolver)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- *aDnsUseHostResolver = mData->mDnsUseHostResolver;
+ *aDNSUseHostResolver = mData->mDNSUseHostResolver;
return S_OK;
}
STDMETHODIMP
-NATEngine::COMSETTER(DnsUseHostResolver)(BOOL aDnsUseHostResolver)
+NATEngine::COMSETTER(DNSUseHostResolver)(BOOL aDNSUseHostResolver)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (mData->mDnsUseHostResolver != aDnsUseHostResolver)
+ if (mData->mDNSUseHostResolver != aDNSUseHostResolver)
{
mData.backup();
- mData->mDnsUseHostResolver = aDnsUseHostResolver;
+ mData->mDNSUseHostResolver = aDNSUseHostResolver;
mParent->setModified(Machine::IsModified_NetworkAdapters);
m_fModified = true;
}
return S_OK;
}
-STDMETHODIMP NATEngine::COMSETTER(AliasMode) (ULONG aAliasMode)
+STDMETHODIMP NATEngine::COMSETTER(AliasMode)(ULONG aAliasMode)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
@@ -663,10 +663,10 @@ STDMETHODIMP NATEngine::COMSETTER(AliasMode) (ULONG aAliasMode)
return S_OK;
}
-STDMETHODIMP NATEngine::COMGETTER(AliasMode) (ULONG *aAliasMode)
+STDMETHODIMP NATEngine::COMGETTER(AliasMode)(ULONG *aAliasMode)
{
AutoCaller autoCaller(this);
- AssertComRCReturnRC (autoCaller.rc());
+ AssertComRCReturnRC(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
*aAliasMode = mData->mAliasMode;
return S_OK;
diff --git a/src/VBox/Main/src-server/NetworkAdapterImpl.cpp b/src/VBox/Main/src-server/NetworkAdapterImpl.cpp
index 2a4364a63..c7e1fa175 100644
--- a/src/VBox/Main/src-server/NetworkAdapterImpl.cpp
+++ b/src/VBox/Main/src-server/NetworkAdapterImpl.cpp
@@ -1,10 +1,10 @@
/* $Id: NetworkAdapterImpl.cpp $ */
/** @file
- * Implementation of INetworkAdaptor in VBoxSVC.
+ * Implementation of INetworkAdapter in VBoxSVC.
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -22,6 +22,7 @@
#include "MachineImpl.h"
#include "GuestOSTypeImpl.h"
#include "HostImpl.h"
+#include "SystemPropertiesImpl.h"
#include <iprt/string.h>
#include <iprt/cpp/utils.h>
@@ -68,7 +69,8 @@ HRESULT NetworkAdapter::init(Machine *aParent, ULONG aSlot)
LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
ComAssertRet(aParent, E_INVALIDARG);
- ComAssertRet(aSlot < SchemaDefs::NetworkAdapterCount, E_INVALIDARG);
+ uint32_t maxNetworkAdapters = Global::getMaxNetworkAdapters(aParent->getChipsetType());
+ ComAssertRet(aSlot < maxNetworkAdapters, E_INVALIDARG);
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
@@ -105,14 +107,19 @@ HRESULT NetworkAdapter::init(Machine *aParent, ULONG aSlot)
* (a kind of copy constructor). This object shares data with
* the object passed as an argument.
*
+ * @param aReshare
+ * When false, the original object will remain a data owner.
+ * Otherwise, data ownership will be transferred from the original
+ * object to this one.
+ *
* @note This object must be destroyed before the original object
* it shares data with is destroyed.
*
* @note Locks @a aThat object for reading.
*/
-HRESULT NetworkAdapter::init(Machine *aParent, NetworkAdapter *aThat)
+HRESULT NetworkAdapter::init(Machine *aParent, NetworkAdapter *aThat, bool aReshare /* = false */)
{
- LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
+ LogFlowThisFunc(("aParent=%p, aThat=%p, aReshare=%RTbool\n", aParent, aThat, aReshare));
ComAssertRet(aParent && aThat, E_INVALIDARG);
@@ -121,15 +128,27 @@ HRESULT NetworkAdapter::init(Machine *aParent, NetworkAdapter *aThat)
AssertReturn(autoInitSpan.isOk(), E_FAIL);
unconst(mParent) = aParent;
- unconst(mPeer) = aThat;
unconst(mNATEngine).createObject();
mNATEngine->init(aParent, this, aThat->mNATEngine);
- AutoCaller thatCaller (aThat);
+ /* sanity */
+ AutoCaller thatCaller(aThat);
AssertComRCReturnRC(thatCaller.rc());
- AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
- mData.share (aThat->mData);
+ if (aReshare)
+ {
+ AutoWriteLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
+
+ unconst(aThat->mPeer) = this;
+ mData.attach(aThat->mData);
+ }
+ else
+ {
+ unconst(mPeer) = aThat;
+
+ AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
+ mData.share(aThat->mData);
+ }
/* Confirm a successful initialization */
autoInitSpan.setSucceeded();
@@ -160,11 +179,11 @@ HRESULT NetworkAdapter::initCopy(Machine *aParent, NetworkAdapter *aThat)
unconst(mNATEngine).createObject();
mNATEngine->initCopy(aParent, this, aThat->mNATEngine);
- AutoCaller thatCaller (aThat);
+ AutoCaller thatCaller(aThat);
AssertComRCReturnRC(thatCaller.rc());
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
- mData.attachCopy (aThat->mData);
+ mData.attachCopy(aThat->mData);
/* Confirm a successful initialization */
autoInitSpan.setSucceeded();
@@ -195,7 +214,7 @@ void NetworkAdapter::uninit()
// INetworkAdapter properties
////////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType) (NetworkAdapterType_T *aAdapterType)
+STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType)(NetworkAdapterType_T *aAdapterType)
{
CheckComArgOutPointerValid(aAdapterType);
@@ -209,7 +228,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(AdapterType) (NetworkAdapterType_T *aAdap
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType) (NetworkAdapterType_T aAdapterType)
+STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType)(NetworkAdapterType_T aAdapterType)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -261,7 +280,7 @@ STDMETHODIMP NetworkAdapter::COMSETTER(AdapterType) (NetworkAdapterType_T aAdapt
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(Slot) (ULONG *aSlot)
+STDMETHODIMP NetworkAdapter::COMGETTER(Slot)(ULONG *aSlot)
{
CheckComArgOutPointerValid(aSlot);
@@ -275,7 +294,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(Slot) (ULONG *aSlot)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(Enabled) (BOOL *aEnabled)
+STDMETHODIMP NetworkAdapter::COMGETTER(Enabled)(BOOL *aEnabled)
{
CheckComArgOutPointerValid(aEnabled);
@@ -289,7 +308,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(Enabled) (BOOL *aEnabled)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(Enabled) (BOOL aEnabled)
+STDMETHODIMP NetworkAdapter::COMSETTER(Enabled)(BOOL aEnabled)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -577,7 +596,7 @@ STDMETHODIMP NetworkAdapter::COMSETTER(HostOnlyInterface)(IN_BSTR aHostOnlyInter
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
+STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork)(BSTR *aInternalNetwork)
{
CheckComArgOutPointerValid(aInternalNetwork);
@@ -591,7 +610,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(InternalNetwork) (BSTR *aInternalNetwork)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (IN_BSTR aInternalNetwork)
+STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork)(IN_BSTR aInternalNetwork)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -633,7 +652,7 @@ STDMETHODIMP NetworkAdapter::COMSETTER(InternalNetwork) (IN_BSTR aInternalNetwor
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork) (BSTR *aNATNetwork)
+STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork)(BSTR *aNATNetwork)
{
CheckComArgOutPointerValid(aNATNetwork);
@@ -647,7 +666,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(NATNetwork) (BSTR *aNATNetwork)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork) (IN_BSTR aNATNetwork)
+STDMETHODIMP NetworkAdapter::COMSETTER(NATNetwork)(IN_BSTR aNATNetwork)
{
Bstr bstrEmpty("");
if (!aNATNetwork)
@@ -726,7 +745,7 @@ STDMETHODIMP NetworkAdapter::COMSETTER(GenericDriver)(IN_BSTR aGenericDriver)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
+STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected)(BOOL *aConnected)
{
CheckComArgOutPointerValid(aConnected);
@@ -740,7 +759,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL *aConnected)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
+STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected)(BOOL aConnected)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -771,7 +790,7 @@ STDMETHODIMP NetworkAdapter::COMSETTER(CableConnected) (BOOL aConnected)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed) (ULONG *aSpeed)
+STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed)(ULONG *aSpeed)
{
CheckComArgOutPointerValid(aSpeed);
@@ -785,7 +804,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(LineSpeed) (ULONG *aSpeed)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed) (ULONG aSpeed)
+STDMETHODIMP NetworkAdapter::COMSETTER(LineSpeed)(ULONG aSpeed)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -864,7 +883,7 @@ STDMETHODIMP NetworkAdapter::COMSETTER(PromiscModePolicy)(NetworkAdapterPromiscM
return hrc;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
+STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled)(BOOL *aEnabled)
{
CheckComArgOutPointerValid(aEnabled);
@@ -877,7 +896,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(TraceEnabled) (BOOL *aEnabled)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
+STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled)(BOOL aEnabled)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -908,7 +927,7 @@ STDMETHODIMP NetworkAdapter::COMSETTER(TraceEnabled) (BOOL aEnabled)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
+STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile)(BSTR *aTraceFile)
{
CheckComArgOutPointerValid(aTraceFile);
@@ -922,7 +941,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(TraceFile) (BSTR *aTraceFile)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (IN_BSTR aTraceFile)
+STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile)(IN_BSTR aTraceFile)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -953,21 +972,21 @@ STDMETHODIMP NetworkAdapter::COMSETTER(TraceFile) (IN_BSTR aTraceFile)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(NatDriver) (INATEngine **aNatDriver)
+STDMETHODIMP NetworkAdapter::COMGETTER(NATEngine)(INATEngine **aNATEngine)
{
- CheckComArgOutPointerValid(aNatDriver);
+ CheckComArgOutPointerValid(aNATEngine);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- mNATEngine.queryInterfaceTo(aNatDriver);
+ mNATEngine.queryInterfaceTo(aNATEngine);
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(BootPriority) (ULONG *aBootPriority)
+STDMETHODIMP NetworkAdapter::COMGETTER(BootPriority)(ULONG *aBootPriority)
{
CheckComArgOutPointerValid(aBootPriority);
@@ -981,7 +1000,7 @@ STDMETHODIMP NetworkAdapter::COMGETTER(BootPriority) (ULONG *aBootPriority)
return S_OK;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(BootPriority) (ULONG aBootPriority)
+STDMETHODIMP NetworkAdapter::COMSETTER(BootPriority)(ULONG aBootPriority)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1174,13 +1193,13 @@ HRESULT NetworkAdapter::loadSettings(BandwidthControl *bwctl,
/* boot priority (defaults to 0, i.e. lowest) */
mData->mBootPriority = data.ulBootPriority;
/* bandwidth group */
- if (data.strBandwidthGroup.isEmpty())
- updateBandwidthGroup(NULL);
- else
+ mData->mBandwidthGroup = data.strBandwidthGroup;
+ if (mData->mBandwidthGroup.isNotEmpty())
{
ComObjPtr<BandwidthGroup> group;
rc = bwctl->getBandwidthGroupByName(data.strBandwidthGroup, group, true);
if (FAILED(rc)) return rc;
+ group->reference();
}
mNATEngine->loadSettings(data.nat);
@@ -1231,10 +1250,7 @@ HRESULT NetworkAdapter::saveSettings(settings::NetworkAdapter &data)
data.ulBootPriority = mData->mBootPriority;
- if (mData->mBandwidthGroup.isNull())
- data.strBandwidthGroup = "";
- else
- data.strBandwidthGroup = mData->mBandwidthGroup->getName();
+ data.strBandwidthGroup = mData->mBandwidthGroup;
data.type = mData->mAdapterType;
@@ -1291,11 +1307,11 @@ void NetworkAdapter::commit()
{
/* sanity */
AutoCaller autoCaller(this);
- AssertComRCReturnVoid (autoCaller.rc());
+ AssertComRCReturnVoid(autoCaller.rc());
/* sanity too */
- AutoCaller peerCaller (mPeer);
- AssertComRCReturnVoid (peerCaller.rc());
+ AutoCaller peerCaller(mPeer);
+ AssertComRCReturnVoid(peerCaller.rc());
/* lock both for writing since we modify both (mPeer is "master" so locked
* first) */
@@ -1307,7 +1323,7 @@ void NetworkAdapter::commit()
if (mPeer)
{
/* attach new data to the peer and reshare it */
- mPeer->mData.attach (mData);
+ mPeer->mData.attach(mData);
}
}
}
@@ -1316,17 +1332,17 @@ void NetworkAdapter::commit()
* @note Locks this object for writing, together with the peer object
* represented by @a aThat (locked for reading).
*/
-void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
+void NetworkAdapter::copyFrom(NetworkAdapter *aThat)
{
- AssertReturnVoid (aThat != NULL);
+ AssertReturnVoid(aThat != NULL);
/* sanity */
AutoCaller autoCaller(this);
- AssertComRCReturnVoid (autoCaller.rc());
+ AssertComRCReturnVoid(autoCaller.rc());
/* sanity too */
- AutoCaller thatCaller (aThat);
- AssertComRCReturnVoid (thatCaller.rc());
+ AutoCaller thatCaller(aThat);
+ AssertComRCReturnVoid(thatCaller.rc());
/* peer is not modified, lock it for reading (aThat is "master" so locked
* first) */
@@ -1334,16 +1350,16 @@ void NetworkAdapter::copyFrom (NetworkAdapter *aThat)
AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
/* this will back up current data */
- mData.assignCopy (aThat->mData);
+ mData.assignCopy(aThat->mData);
}
-void NetworkAdapter::applyDefaults (GuestOSType *aOsType)
+void NetworkAdapter::applyDefaults(GuestOSType *aOsType)
{
- AssertReturnVoid (aOsType != NULL);
+ AssertReturnVoid(aOsType != NULL);
/* sanity */
AutoCaller autoCaller(this);
- AssertComRCReturnVoid (autoCaller.rc());
+ AssertComRCReturnVoid(autoCaller.rc());
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -1372,6 +1388,12 @@ void NetworkAdapter::applyDefaults (GuestOSType *aOsType)
}
}
+ComObjPtr<NetworkAdapter> NetworkAdapter::getPeer()
+{
+ return mPeer;
+}
+
+
// private methods
////////////////////////////////////////////////////////////////////////////////
@@ -1390,23 +1412,34 @@ void NetworkAdapter::generateMACAddress()
mData->mMACAddress = mac;
}
-STDMETHODIMP NetworkAdapter::COMGETTER(BandwidthGroup) (IBandwidthGroup **aBwGroup)
+STDMETHODIMP NetworkAdapter::COMGETTER(BandwidthGroup)(IBandwidthGroup **aBwGroup)
{
LogFlowThisFuncEnter();
CheckComArgOutPointerValid(aBwGroup);
+ HRESULT hrc = S_OK;
+
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- mData->mBandwidthGroup.queryInterfaceTo(aBwGroup);
+ if (mData->mBandwidthGroup.isNotEmpty())
+ {
+ ComObjPtr<BandwidthGroup> pBwGroup;
+ hrc = mParent->getBandwidthGroup(mData->mBandwidthGroup, pBwGroup, true /* fSetError */);
+
+ Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
+
+ if (SUCCEEDED(hrc))
+ pBwGroup.queryInterfaceTo(aBwGroup);
+ }
LogFlowThisFuncLeave();
- return S_OK;
+ return hrc;
}
-STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthGroup) (IBandwidthGroup *aBwGroup)
+STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthGroup)(IBandwidthGroup *aBwGroup)
{
LogFlowThisFuncEnter();
@@ -1419,11 +1452,20 @@ STDMETHODIMP NetworkAdapter::COMSETTER(BandwidthGroup) (IBandwidthGroup *aBwGrou
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- if (mData->mBandwidthGroup != aBwGroup)
+ Utf8Str strBwGroup;
+ if (aBwGroup)
+ strBwGroup = static_cast<BandwidthGroup*>(aBwGroup)->getName();
+ if (mData->mBandwidthGroup != strBwGroup)
{
- mData.backup();
+ ComObjPtr<BandwidthGroup> pBwGroup;
+ if (!strBwGroup.isEmpty())
+ {
+ HRESULT hrc = mParent->getBandwidthGroup(strBwGroup, pBwGroup, false /* fSetError */);
+ NOREF(hrc);
+ Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
+ }
- updateBandwidthGroup(static_cast<BandwidthGroup*>(aBwGroup));
+ updateBandwidthGroup(pBwGroup);
m_fModified = true;
// leave the lock before informing callbacks
@@ -1446,17 +1488,25 @@ void NetworkAdapter::updateBandwidthGroup(BandwidthGroup *aBwGroup)
LogFlowThisFuncEnter();
Assert(isWriteLockOnCurrentThread());
+ ComObjPtr<BandwidthGroup> pOldBwGroup;
+ if (!mData->mBandwidthGroup.isEmpty())
+ {
+ HRESULT hrc = mParent->getBandwidthGroup(mData->mBandwidthGroup, pOldBwGroup, false /* fSetError */);
+ NOREF(hrc);
+ Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the group was checked when it was attached. */
+ }
+
mData.backup();
- if (!mData->mBandwidthGroup.isNull())
+ if (!pOldBwGroup.isNull())
{
- mData->mBandwidthGroup->release();
- mData->mBandwidthGroup.setNull();
+ pOldBwGroup->release();
+ mData->mBandwidthGroup = Utf8Str::Empty;
}
if (aBwGroup)
{
- mData->mBandwidthGroup = aBwGroup;
- mData->mBandwidthGroup->reference();
+ mData->mBandwidthGroup = aBwGroup->getName();
+ aBwGroup->reference();
}
LogFlowThisFuncLeave();
diff --git a/src/VBox/Main/src-server/Performance.cpp b/src/VBox/Main/src-server/Performance.cpp
index 315c46f71..1ee789be6 100644
--- a/src/VBox/Main/src-server/Performance.cpp
+++ b/src/VBox/Main/src-server/Performance.cpp
@@ -24,6 +24,8 @@
#ifndef VBOX_COLLECTOR_TEST_CASE
#include "VirtualBoxImpl.h"
#include "MachineImpl.h"
+#include "MediumImpl.h"
+#include "AutoCaller.h"
#endif
#include "Performance.h"
@@ -58,6 +60,16 @@ int CollectorHAL::getRawHostCpuLoad(uint64_t * /* user */, uint64_t * /* kernel
return E_NOTIMPL;
}
+int CollectorHAL::getRawHostNetworkLoad(const char * /* name */, uint64_t * /* rx */, uint64_t * /* tx */)
+{
+ return E_NOTIMPL;
+}
+
+int CollectorHAL::getRawHostDiskLoad(const char * /* name */, uint64_t * /* disk_ms */, uint64_t * /* total_ms */)
+{
+ return E_NOTIMPL;
+}
+
int CollectorHAL::getRawProcessCpuLoad(RTPROCESS /* process */, uint64_t * /* user */, uint64_t * /* kernel */, uint64_t * /* total */)
{
return E_NOTIMPL;
@@ -68,11 +80,26 @@ int CollectorHAL::getHostMemoryUsage(ULONG * /* total */, ULONG * /* used */, UL
return E_NOTIMPL;
}
+int CollectorHAL::getHostFilesystemUsage(const char * /* name */, ULONG * /* total */, ULONG * /* used */, ULONG * /* available */)
+{
+ return E_NOTIMPL;
+}
+
+int CollectorHAL::getHostDiskSize(const char * /* name */, uint64_t * /* size */)
+{
+ return E_NOTIMPL;
+}
+
int CollectorHAL::getProcessMemoryUsage(RTPROCESS /* process */, ULONG * /* used */)
{
return E_NOTIMPL;
}
+int CollectorHAL::getDiskListByFs(const char * /* name */, DiskList& /* list */)
+{
+ return E_NOTIMPL;
+}
+
/* Generic implementations */
int CollectorHAL::getHostCpuMHz(ULONG *mhz)
@@ -202,7 +229,7 @@ CollectorGuest::CollectorGuest(Machine *machine, RTPROCESS process) :
mUnregistered(false), mEnabled(false), mValid(false), mMachine(machine), mProcess(process),
mCpuUser(0), mCpuKernel(0), mCpuIdle(0),
mMemTotal(0), mMemFree(0), mMemBalloon(0), mMemShared(0), mMemCache(0), mPageTotal(0),
- mAllocVMM(0), mFreeVMM(0), mBalloonedVMM(0), mSharedVMM(0)
+ mAllocVMM(0), mFreeVMM(0), mBalloonedVMM(0), mSharedVMM(0), mVmNetRx(0), mVmNetTx(0)
{
Assert(mMachine);
/* cannot use ComObjPtr<Machine> in Performance.h, do it manually */
@@ -291,7 +318,7 @@ int CollectorGuest::enableInternal(ULONG mask)
this, __PRETTY_FUNCTION__, SUCCEEDED(ret)?"success":"failed"));
}
}
- if ((mask & GUESTSTATS_VMMRAM) == GUESTSTATS_VMMRAM)
+ if ((mask & VMSTATS_VMM_RAM) == VMSTATS_VMM_RAM)
enableVMMStats(true);
mEnabled |= mask;
@@ -303,7 +330,7 @@ int CollectorGuest::disableInternal(ULONG mask)
if (!(mEnabled & mask))
return E_UNEXPECTED;
- if ((mask & GUESTSTATS_VMMRAM) == GUESTSTATS_VMMRAM)
+ if ((mask & VMSTATS_VMM_RAM) == VMSTATS_VMM_RAM)
enableVMMStats(false);
mEnabled &= ~mask;
if (!mEnabled)
@@ -313,7 +340,7 @@ int CollectorGuest::disableInternal(ULONG mask)
NOREF(ret);
LogAleksey(("{%p} " LOG_FN_FMT ": Set guest statistics update interval to 0 sec (%s)\n",
this, __PRETTY_FUNCTION__, SUCCEEDED(ret)?"success":"failed"));
- invalidate(GUESTSTATS_ALL);
+ invalidate(VMSTATS_ALL);
}
return S_OK;
@@ -338,15 +365,16 @@ void CollectorGuest::updateStats(ULONG aValidStats, ULONG aCpuUser,
ULONG aMemBalloon, ULONG aMemShared,
ULONG aMemCache, ULONG aPageTotal,
ULONG aAllocVMM, ULONG aFreeVMM,
- ULONG aBalloonedVMM, ULONG aSharedVMM)
+ ULONG aBalloonedVMM, ULONG aSharedVMM,
+ ULONG aVmNetRx, ULONG aVmNetTx)
{
- if ((aValidStats & GUESTSTATS_CPULOAD) == GUESTSTATS_CPULOAD)
+ if ((aValidStats & VMSTATS_GUEST_CPULOAD) == VMSTATS_GUEST_CPULOAD)
{
mCpuUser = aCpuUser;
mCpuKernel = aCpuKernel,
mCpuIdle = aCpuIdle;
}
- if ((aValidStats & GUESTSTATS_RAMUSAGE) == GUESTSTATS_RAMUSAGE)
+ if ((aValidStats & VMSTATS_GUEST_RAMUSAGE) == VMSTATS_GUEST_RAMUSAGE)
{
mMemTotal = aMemTotal;
mMemFree = aMemFree;
@@ -355,13 +383,18 @@ void CollectorGuest::updateStats(ULONG aValidStats, ULONG aCpuUser,
mMemCache = aMemCache;
mPageTotal = aPageTotal;
}
- if ((aValidStats & GUESTSTATS_VMMRAM) == GUESTSTATS_VMMRAM)
+ if ((aValidStats & VMSTATS_VMM_RAM) == VMSTATS_VMM_RAM)
{
mAllocVMM = aAllocVMM;
mFreeVMM = aFreeVMM;
mBalloonedVMM = aBalloonedVMM;
mSharedVMM = aSharedVMM;
}
+ if ((aValidStats & VMSTATS_NET_RATE) == VMSTATS_NET_RATE)
+ {
+ mVmNetRx = aVmNetRx;
+ mVmNetTx = aVmNetTx;
+ }
mValid = aValidStats;
}
@@ -431,7 +464,7 @@ void CollectorGuestManager::unregisterGuest(CollectorGuest* pGuest)
{
/* Found the guest already collecting stats, elect it */
mVMMStatsProvider = *it;
- rc = mVMMStatsProvider->enqueueRequest(new CGRQEnable(GUESTSTATS_VMMRAM));
+ rc = mVMMStatsProvider->enqueueRequest(new CGRQEnable(VMSTATS_VMM_RAM));
if (FAILED(rc))
{
/* This is not a good candidate -- try to find another */
@@ -451,8 +484,8 @@ void CollectorGuestManager::unregisterGuest(CollectorGuest* pGuest)
continue;
mVMMStatsProvider = *it;
- //mVMMStatsProvider->enable(GUESTSTATS_VMMRAM);
- rc = mVMMStatsProvider->enqueueRequest(new CGRQEnable(GUESTSTATS_VMMRAM));
+ //mVMMStatsProvider->enable(VMSTATS_VMM_RAM);
+ rc = mVMMStatsProvider->enqueueRequest(new CGRQEnable(VMSTATS_VMM_RAM));
if (SUCCEEDED(rc))
break;
/* This was not a good candidate -- try to find another */
@@ -553,13 +586,32 @@ bool BaseMetric::collectorBeat(uint64_t nowAt)
{
if (isEnabled())
{
- if (nowAt - mLastSampleTaken >= mPeriod * 1000)
+ if (mLastSampleTaken == 0)
{
mLastSampleTaken = nowAt;
Log4(("{%p} " LOG_FN_FMT ": Collecting %s for obj(%p)...\n",
this, __PRETTY_FUNCTION__, getName(), (void *)mObject));
return true;
}
+ /*
+ * We use low resolution timers which may fire just a little bit early.
+ * We compensate for that by jumping into the future by several
+ * milliseconds (see @bugref{6345}).
+ */
+ if (nowAt - mLastSampleTaken + PM_SAMPLER_PRECISION_MS >= mPeriod * 1000)
+ {
+ /*
+ * We don't want the beat to drift. This is why the timestamp of
+ * the last taken sample is not the actual time but the time we
+ * should have taken the measurement at.
+ */
+ mLastSampleTaken += mPeriod * 1000;
+ Log4(("{%p} " LOG_FN_FMT ": Collecting %s for obj(%p)...\n",
+ this, __PRETTY_FUNCTION__, getName(), (void *)mObject));
+ return true;
+ }
+ Log4(("{%p} " LOG_FN_FMT ": Enabled but too early to collect %s for obj(%p)\n",
+ this, __PRETTY_FUNCTION__, getName(), (void *)mObject));
}
return false;
}
@@ -625,6 +677,122 @@ void HostCpuLoadRaw::collect()
}
}
+void HostNetworkLoadRaw::init(ULONG period, ULONG length)
+{
+ mPeriod = period;
+ mLength = length;
+ mRx->init(mLength);
+ mTx->init(mLength);
+ /*int rc =*/ mHAL->getRawHostNetworkLoad(mShortName.c_str(), &mRxPrev, &mTxPrev);
+ //AssertRC(rc);
+}
+
+void HostNetworkLoadRaw::preCollect(CollectorHints& /* hints */, uint64_t /* iTick */)
+{
+ if (RT_FAILURE(mRc))
+ {
+ ComPtr<IHostNetworkInterface> networkInterface;
+ ComPtr<IHost> host = getObject();
+ HRESULT hrc = host->FindHostNetworkInterfaceByName(com::Bstr(mInterfaceName).raw(), networkInterface.asOutParam());
+ if (SUCCEEDED(hrc))
+ {
+ LogRel(("Failed to collect network metrics for %s: %Rrc (%d).\n", mInterfaceName.c_str(), mRc, mRc));
+ mRc = VINF_SUCCESS;
+ }
+ }
+}
+
+void HostNetworkLoadRaw::collect()
+{
+ uint64_t rx = mRxPrev;
+ uint64_t tx = mTxPrev;
+
+ if (RT_UNLIKELY(mSpeed * getPeriod() == 0))
+ {
+ LogFlowThisFunc(("Check cable for %s! speed=%llu period=%d.\n", mShortName.c_str(), mSpeed, getPeriod()));
+ /* We do not collect host network metrics for unplugged interfaces! */
+ return;
+ }
+ mRc = mHAL->getRawHostNetworkLoad(mShortName.c_str(), &rx, &tx);
+ if (RT_SUCCESS(mRc))
+ {
+ uint64_t rxDiff = rx - mRxPrev;
+ uint64_t txDiff = tx - mTxPrev;
+
+ mRx->put((ULONG)(PM_NETWORK_LOAD_MULTIPLIER * rxDiff / (mSpeed * getPeriod())));
+ mTx->put((ULONG)(PM_NETWORK_LOAD_MULTIPLIER * txDiff / (mSpeed * getPeriod())));
+
+ mRxPrev = rx;
+ mTxPrev = tx;
+ }
+ else
+ LogFlowThisFunc(("Failed to collect data: %Rrc (%d)."
+ " Will update the list of interfaces...\n", mRc,mRc));
+}
+
+void HostDiskLoadRaw::init(ULONG period, ULONG length)
+{
+ mPeriod = period;
+ mLength = length;
+ mUtil->init(mLength);
+ int rc = mHAL->getRawHostDiskLoad(mDiskName.c_str(), &mDiskPrev, &mTotalPrev);
+ AssertRC(rc);
+}
+
+void HostDiskLoadRaw::preCollect(CollectorHints& hints, uint64_t /* iTick */)
+{
+ hints.collectHostCpuLoad();
+}
+
+void HostDiskLoadRaw::collect()
+{
+ uint64_t disk, total;
+
+ int rc = mHAL->getRawHostDiskLoad(mDiskName.c_str(), &disk, &total);
+ if (RT_SUCCESS(rc))
+ {
+ uint64_t diskDiff = disk - mDiskPrev;
+ uint64_t totalDiff = total - mTotalPrev;
+
+ if (RT_UNLIKELY(totalDiff == 0))
+ {
+ Assert(totalDiff);
+ LogFlowThisFunc(("Improbable! Less than millisecond passed! Disk=%s\n", mDiskName.c_str()));
+ mUtil->put(0);
+ }
+ else if (diskDiff > totalDiff)
+ {
+ /*
+ * It is possible that the disk spent more time than CPU because
+ * CPU measurements are taken during the pre-collect phase. We try
+ * to compensate for than by adding the extra to the next round of
+ * measurements.
+ */
+ mUtil->put(PM_NETWORK_LOAD_MULTIPLIER);
+ Assert((diskDiff - totalDiff) < mPeriod * 1000);
+ if ((diskDiff - totalDiff) > mPeriod * 1000)
+ {
+ LogRel(("Disk utilization time exceeds CPU time by more"
+ " than the collection period (%llu ms)\n", diskDiff - totalDiff));
+ }
+ else
+ {
+ disk = mDiskPrev + totalDiff;
+ LogFlowThisFunc(("Moved %u milliseconds to the next period.\n", (unsigned)(diskDiff - totalDiff)));
+ }
+ }
+ else
+ {
+ mUtil->put((ULONG)(PM_NETWORK_LOAD_MULTIPLIER * diskDiff / totalDiff));
+ }
+
+ mDiskPrev = disk;
+ mTotalPrev = total;
+ }
+ else
+ LogFlowThisFunc(("Failed to collect data: %Rrc (%d).\n", rc));
+}
+
void HostCpuMhz::init(ULONG period, ULONG length)
{
mPeriod = period;
@@ -667,6 +835,51 @@ void HostRamUsage::collect()
}
}
+void HostFilesystemUsage::init(ULONG period, ULONG length)
+{
+ mPeriod = period;
+ mLength = length;
+ mTotal->init(mLength);
+ mUsed->init(mLength);
+ mAvailable->init(mLength);
+}
+
+void HostFilesystemUsage::preCollect(CollectorHints& /* hints */, uint64_t /* iTick */)
+{
+}
+
+void HostFilesystemUsage::collect()
+{
+ ULONG total, used, available;
+ int rc = mHAL->getHostFilesystemUsage(mFsName.c_str(), &total, &used, &available);
+ if (RT_SUCCESS(rc))
+ {
+ mTotal->put(total);
+ mUsed->put(used);
+ mAvailable->put(available);
+
+ }
+}
+
+void HostDiskUsage::init(ULONG period, ULONG length)
+{
+ mPeriod = period;
+ mLength = length;
+ mTotal->init(mLength);
+}
+
+void HostDiskUsage::preCollect(CollectorHints& /* hints */, uint64_t /* iTick */)
+{
+}
+
+void HostDiskUsage::collect()
+{
+ uint64_t total;
+ int rc = mHAL->getHostDiskSize(mDiskName.c_str(), &total);
+ if (RT_SUCCESS(rc))
+ mTotal->put((ULONG)(total / (1024*1024)));
+}
+
#ifndef VBOX_COLLECTOR_TEST_CASE
void HostRamVmm::init(ULONG period, ULONG length)
{
@@ -683,7 +896,7 @@ int HostRamVmm::enable()
int rc = S_OK;
CollectorGuest *provider = mCollectorGuestManager->getVMMStatsProvider();
if (provider)
- rc = provider->enable(GUESTSTATS_VMMRAM);
+ rc = provider->enable(VMSTATS_VMM_RAM);
BaseMetric::enable();
return rc;
}
@@ -694,7 +907,7 @@ int HostRamVmm::disable()
BaseMetric::disable();
CollectorGuest *provider = mCollectorGuestManager->getVMMStatsProvider();
if (provider)
- rc = provider->disable(GUESTSTATS_VMMRAM);
+ rc = provider->disable(VMSTATS_VMM_RAM);
return rc;
}
@@ -710,15 +923,15 @@ void HostRamVmm::collect()
{
LogAleksey(("{%p} " LOG_FN_FMT ": provider=%p enabled=%s valid=%s...\n",
this, __PRETTY_FUNCTION__, provider, provider->isEnabled()?"y":"n",
- provider->isValid(GUESTSTATS_VMMRAM)?"y":"n"));
- if (provider->isValid(GUESTSTATS_VMMRAM))
+ provider->isValid(VMSTATS_VMM_RAM)?"y":"n"));
+ if (provider->isValid(VMSTATS_VMM_RAM))
{
/* Provider is ready, get updated stats */
mAllocCurrent = provider->getAllocVMM();
mFreeCurrent = provider->getFreeVMM();
mBalloonedCurrent = provider->getBalloonedVMM();
mSharedCurrent = provider->getSharedVMM();
- provider->invalidate(GUESTSTATS_VMMRAM);
+ provider->invalidate(VMSTATS_VMM_RAM);
}
/*
* Note that if there are no new values from the provider we will use
@@ -816,6 +1029,76 @@ void MachineRamUsage::collect()
#ifndef VBOX_COLLECTOR_TEST_CASE
+void MachineDiskUsage::init(ULONG period, ULONG length)
+{
+ mPeriod = period;
+ mLength = length;
+ mUsed->init(mLength);
+}
+
+void MachineDiskUsage::preCollect(CollectorHints& /* hints */, uint64_t /* iTick */)
+{
+}
+
+void MachineDiskUsage::collect()
+{
+ ULONG used = 0;
+
+ for (MediaList::iterator it = mDisks.begin(); it != mDisks.end(); ++it)
+ {
+ ComObjPtr<Medium> pMedium = *it;
+
+ /* just in case */
+ AssertStmt(!pMedium.isNull(), continue);
+
+ AutoCaller localAutoCaller(pMedium);
+ if (FAILED(localAutoCaller.rc())) continue;
+
+ AutoReadLock local_alock(pMedium COMMA_LOCKVAL_SRC_POS);
+
+ used += pMedium->getSize() / (1024 * 1024);
+ }
+
+ mUsed->put(used);
+}
+
+void MachineNetRate::init(ULONG period, ULONG length)
+{
+ mPeriod = period;
+ mLength = length;
+
+ mRx->init(mLength);
+ mTx->init(mLength);
+}
+
+void MachineNetRate::collect()
+{
+ if (mCGuest->isValid(VMSTATS_NET_RATE))
+ {
+ mRx->put(mCGuest->getVmNetRx());
+ mTx->put(mCGuest->getVmNetTx());
+ mCGuest->invalidate(VMSTATS_NET_RATE);
+ }
+}
+
+int MachineNetRate::enable()
+{
+ int rc = mCGuest->enable(VMSTATS_NET_RATE);
+ BaseMetric::enable();
+ return rc;
+}
+
+int MachineNetRate::disable()
+{
+ BaseMetric::disable();
+ return mCGuest->disable(VMSTATS_NET_RATE);
+}
+
+void MachineNetRate::preCollect(CollectorHints& hints, uint64_t /* iTick */)
+{
+ hints.collectGuestStats(mCGuest->getProcess());
+}
+
void GuestCpuLoad::init(ULONG period, ULONG length)
{
mPeriod = period;
@@ -833,18 +1116,18 @@ void GuestCpuLoad::preCollect(CollectorHints& hints, uint64_t /* iTick */)
void GuestCpuLoad::collect()
{
- if (mCGuest->isValid(GUESTSTATS_CPULOAD))
+ if (mCGuest->isValid(VMSTATS_GUEST_CPULOAD))
{
mUser->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * mCGuest->getCpuUser()) / 100);
mKernel->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * mCGuest->getCpuKernel()) / 100);
mIdle->put((ULONG)(PM_CPU_LOAD_MULTIPLIER * mCGuest->getCpuIdle()) / 100);
- mCGuest->invalidate(GUESTSTATS_CPULOAD);
+ mCGuest->invalidate(VMSTATS_GUEST_CPULOAD);
}
}
int GuestCpuLoad::enable()
{
- int rc = mCGuest->enable(GUESTSTATS_CPULOAD);
+ int rc = mCGuest->enable(VMSTATS_GUEST_CPULOAD);
BaseMetric::enable();
return rc;
}
@@ -852,7 +1135,7 @@ int GuestCpuLoad::enable()
int GuestCpuLoad::disable()
{
BaseMetric::disable();
- return mCGuest->disable(GUESTSTATS_CPULOAD);
+ return mCGuest->disable(VMSTATS_GUEST_CPULOAD);
}
void GuestRamUsage::init(ULONG period, ULONG length)
@@ -870,7 +1153,7 @@ void GuestRamUsage::init(ULONG period, ULONG length)
void GuestRamUsage::collect()
{
- if (mCGuest->isValid(GUESTSTATS_RAMUSAGE))
+ if (mCGuest->isValid(VMSTATS_GUEST_RAMUSAGE))
{
mTotal->put(mCGuest->getMemTotal());
mFree->put(mCGuest->getMemFree());
@@ -878,13 +1161,13 @@ void GuestRamUsage::collect()
mShared->put(mCGuest->getMemShared());
mCache->put(mCGuest->getMemCache());
mPagedTotal->put(mCGuest->getPageTotal());
- mCGuest->invalidate(GUESTSTATS_RAMUSAGE);
+ mCGuest->invalidate(VMSTATS_GUEST_RAMUSAGE);
}
}
int GuestRamUsage::enable()
{
- int rc = mCGuest->enable(GUESTSTATS_RAMUSAGE);
+ int rc = mCGuest->enable(VMSTATS_GUEST_RAMUSAGE);
BaseMetric::enable();
return rc;
}
@@ -892,7 +1175,7 @@ int GuestRamUsage::enable()
int GuestRamUsage::disable()
{
BaseMetric::disable();
- return mCGuest->disable(GUESTSTATS_RAMUSAGE);
+ return mCGuest->disable(VMSTATS_GUEST_RAMUSAGE);
}
void GuestRamUsage::preCollect(CollectorHints& hints, uint64_t /* iTick */)
@@ -1072,6 +1355,11 @@ Filter::Filter(ComSafeArrayIn(IN_BSTR, metricNames),
}
}
+Filter::Filter(const com::Utf8Str name, const ComPtr<IUnknown> &aObject)
+{
+ processMetricList(name, aObject);
+}
+
void Filter::init(ComSafeArrayIn(IN_BSTR, metricNames),
ComSafeArrayIn(IUnknown *, objects))
{
@@ -1206,7 +1494,7 @@ bool Filter::match(const ComPtr<IUnknown> object, const RTCString &name) const
// Objects match, compare names
if (patternMatch((*it).second.c_str(), name.c_str()))
{
- LogFlowThisFunc(("...found!\n"));
+ //LogFlowThisFunc(("...found!\n"));
return true;
}
}
diff --git a/src/VBox/Main/src-server/PerformanceImpl.cpp b/src/VBox/Main/src-server/PerformanceImpl.cpp
index d685b901e..b233f0a7a 100644
--- a/src/VBox/Main/src-server/PerformanceImpl.cpp
+++ b/src/VBox/Main/src-server/PerformanceImpl.cpp
@@ -65,6 +65,14 @@ static const char *g_papcszMetricNames[] =
"CPU/MHz:avg",
"CPU/MHz:min",
"CPU/MHz:max",
+ "Net/*/Load/Rx",
+ "Net/*/Load/Rx:avg",
+ "Net/*/Load/Rx:min",
+ "Net/*/Load/Rx:max",
+ "Net/*/Load/Tx",
+ "Net/*/Load/Tx:avg",
+ "Net/*/Load/Tx:min",
+ "Net/*/Load/Tx:max",
"RAM/Usage/Total",
"RAM/Usage/Total:avg",
"RAM/Usage/Total:min",
@@ -590,37 +598,42 @@ void PerformanceCollector::registerMetric(pm::Metric *metric)
//LogFlowThisFuncLeave();
}
-void PerformanceCollector::unregisterBaseMetricsFor(const ComPtr<IUnknown> &aObject)
+void PerformanceCollector::unregisterBaseMetricsFor(const ComPtr<IUnknown> &aObject, const Utf8Str name)
{
//LogFlowThisFuncEnter();
AutoCaller autoCaller(this);
if (!SUCCEEDED(autoCaller.rc())) return;
+ pm::Filter filter(name, aObject);
+
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
int n = 0;
BaseMetricList::iterator it;
for (it = m.baseMetrics.begin(); it != m.baseMetrics.end(); ++it)
- if ((*it)->associatedWith(aObject))
+ if (filter.match((*it)->getObject(), (*it)->getName()))
{
(*it)->unregister();
++n;
}
- LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p, marked %d metrics\n",
- this, __PRETTY_FUNCTION__, (void *)aObject, n));
+ LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p, name=%s, marked %d metrics\n",
+ this, __PRETTY_FUNCTION__, (void *)aObject, name.c_str(), n));
//LogFlowThisFuncLeave();
}
-void PerformanceCollector::unregisterMetricsFor(const ComPtr<IUnknown> &aObject)
+void PerformanceCollector::unregisterMetricsFor(const ComPtr<IUnknown> &aObject, const Utf8Str name)
{
//LogFlowThisFuncEnter();
AutoCaller autoCaller(this);
if (!SUCCEEDED(autoCaller.rc())) return;
+ pm::Filter filter(name, aObject);
+
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p\n", this, __PRETTY_FUNCTION__, (void *)aObject));
+ LogAleksey(("{%p} " LOG_FN_FMT ": obj=%p, name=%s\n", this,
+ __PRETTY_FUNCTION__, (void *)aObject, name.c_str()));
MetricList::iterator it;
for (it = m.metrics.begin(); it != m.metrics.end();)
- if ((*it)->associatedWith(aObject))
+ if (filter.match((*it)->getObject(), (*it)->getName()))
{
delete *it;
it = m.metrics.erase(it);
diff --git a/src/VBox/Main/src-server/SnapshotImpl.cpp b/src/VBox/Main/src-server/SnapshotImpl.cpp
index eff889004..d8aa7a795 100644
--- a/src/VBox/Main/src-server/SnapshotImpl.cpp
+++ b/src/VBox/Main/src-server/SnapshotImpl.cpp
@@ -1,5 +1,4 @@
/* $Id: SnapshotImpl.cpp $ */
-
/** @file
*
* COM class implementation for Snapshot and SnapshotMachine in VBoxSVC.
@@ -42,6 +41,7 @@
#include <VBox/settings.h>
+
////////////////////////////////////////////////////////////////////////////////
//
// Snapshot private data definition
@@ -341,7 +341,7 @@ STDMETHODIMP Snapshot::COMSETTER(Name)(IN_BSTR aName)
if (m->strName != strName)
{
m->strName = strName;
- alock.leave(); /* Important! (child->parent locks are forbidden) */
+ alock.release(); /* Important! (child->parent locks are forbidden) */
rc = m->pMachine->onSnapshotChange(this);
}
@@ -374,7 +374,7 @@ STDMETHODIMP Snapshot::COMSETTER(Description)(IN_BSTR aDescription)
if (m->strDescription != strDescription)
{
m->strDescription = strDescription;
- alock.leave(); /* Important! (child->parent locks are forbidden) */
+ alock.release(); /* Important! (child->parent locks are forbidden) */
rc = m->pMachine->onSnapshotChange(this);
}
@@ -773,7 +773,7 @@ HRESULT Snapshot::saveSnapshotImpl(settings::Snapshot &data, bool aAttrsOnly)
else
data.strStateFile.setNull();
- HRESULT rc = m->pMachine->saveHardware(data.hardware);
+ HRESULT rc = m->pMachine->saveHardware(data.hardware, &data.debugging, &data.autostart);
if (FAILED(rc)) return rc;
rc = m->pMachine->saveStorageControllers(data.storage);
@@ -915,7 +915,12 @@ HRESULT Snapshot::uninitRecursively(AutoWriteLock &writeLock,
//
////////////////////////////////////////////////////////////////////////////////
-DEFINE_EMPTY_CTOR_DTOR(SnapshotMachine)
+SnapshotMachine::SnapshotMachine()
+ : mMachine(NULL)
+{}
+
+SnapshotMachine::~SnapshotMachine()
+{}
HRESULT SnapshotMachine::FinalConstruct()
{
@@ -959,18 +964,20 @@ HRESULT SnapshotMachine::init(SessionMachine *aSessionMachine,
AssertReturn(aSessionMachine->isWriteLockOnCurrentThread(), E_FAIL);
mSnapshotId = aSnapshotId;
+ ComObjPtr<Machine> pMachine = aSessionMachine->mPeer;
+ /* mPeer stays NULL */
/* memorize the primary Machine instance (i.e. not SessionMachine!) */
- unconst(mPeer) = aSessionMachine->mPeer;
+ unconst(mMachine) = pMachine;
/* share the parent pointer */
- unconst(mParent) = mPeer->mParent;
+ unconst(mParent) = pMachine->mParent;
/* take the pointer to Data to share */
- mData.share(mPeer->mData);
+ mData.share(pMachine->mData);
/* take the pointer to UserData to share (our UserData must always be the
* same as Machine's data) */
- mUserData.share(mPeer->mUserData);
+ mUserData.share(pMachine->mUserData);
/* make a private copy of all other data (recent changes from SessionMachine) */
mHWData.attachCopy(aSessionMachine->mHWData);
mMediaData.attachCopy(aSessionMachine->mMediaData);
@@ -1026,37 +1033,38 @@ HRESULT SnapshotMachine::init(SessionMachine *aSessionMachine,
/* create all other child objects that will be immutable private copies */
unconst(mBIOSSettings).createObject();
- mBIOSSettings->initCopy(this, mPeer->mBIOSSettings);
+ mBIOSSettings->initCopy(this, pMachine->mBIOSSettings);
unconst(mVRDEServer).createObject();
- mVRDEServer->initCopy(this, mPeer->mVRDEServer);
+ mVRDEServer->initCopy(this, pMachine->mVRDEServer);
unconst(mAudioAdapter).createObject();
- mAudioAdapter->initCopy(this, mPeer->mAudioAdapter);
+ mAudioAdapter->initCopy(this, pMachine->mAudioAdapter);
unconst(mUSBController).createObject();
- mUSBController->initCopy(this, mPeer->mUSBController);
+ mUSBController->initCopy(this, pMachine->mUSBController);
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); slot++)
+ mNetworkAdapters.resize(pMachine->mNetworkAdapters.size());
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
{
unconst(mNetworkAdapters[slot]).createObject();
- mNetworkAdapters[slot]->initCopy(this, mPeer->mNetworkAdapters[slot]);
+ mNetworkAdapters[slot]->initCopy(this, pMachine->mNetworkAdapters[slot]);
}
for (ULONG slot = 0; slot < RT_ELEMENTS(mSerialPorts); slot++)
{
unconst(mSerialPorts[slot]).createObject();
- mSerialPorts[slot]->initCopy(this, mPeer->mSerialPorts[slot]);
+ mSerialPorts[slot]->initCopy(this, pMachine->mSerialPorts[slot]);
}
for (ULONG slot = 0; slot < RT_ELEMENTS(mParallelPorts); slot++)
{
unconst(mParallelPorts[slot]).createObject();
- mParallelPorts[slot]->initCopy(this, mPeer->mParallelPorts[slot]);
+ mParallelPorts[slot]->initCopy(this, pMachine->mParallelPorts[slot]);
}
unconst(mBandwidthControl).createObject();
- mBandwidthControl->initCopy(this, mPeer->mBandwidthControl);
+ mBandwidthControl->initCopy(this, pMachine->mBandwidthControl);
/* Confirm a successful initialization when it's the case */
autoInitSpan.setSucceeded();
@@ -1077,16 +1085,18 @@ HRESULT SnapshotMachine::init(SessionMachine *aSessionMachine,
*
* @note Doesn't lock anything.
*/
-HRESULT SnapshotMachine::init(Machine *aMachine,
- const settings::Hardware &hardware,
- const settings::Storage &storage,
- IN_GUID aSnapshotId,
- const Utf8Str &aStateFilePath)
+HRESULT SnapshotMachine::initFromSettings(Machine *aMachine,
+ const settings::Hardware &hardware,
+ const settings::Debugging *pDbg,
+ const settings::Autostart *pAutostart,
+ const settings::Storage &storage,
+ IN_GUID aSnapshotId,
+ const Utf8Str &aStateFilePath)
{
LogFlowThisFuncEnter();
LogFlowThisFunc(("mName={%s}\n", aMachine->mUserData->s.strName.c_str()));
- AssertReturn(aMachine && !Guid(aSnapshotId).isEmpty(), E_INVALIDARG);
+ AssertReturn(aMachine && !Guid(aSnapshotId).isEmpty(), E_INVALIDARG);
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
@@ -1096,18 +1106,19 @@ HRESULT SnapshotMachine::init(Machine *aMachine,
mSnapshotId = aSnapshotId;
- /* memorize the primary Machine instance */
- unconst(mPeer) = aMachine;
+ /* mPeer stays NULL */
+ /* memorize the primary Machine instance (i.e. not SessionMachine!) */
+ unconst(mMachine) = aMachine;
/* share the parent pointer */
- unconst(mParent) = mPeer->mParent;
+ unconst(mParent) = aMachine->mParent;
/* take the pointer to Data to share */
- mData.share(mPeer->mData);
+ mData.share(aMachine->mData);
/*
* take the pointer to UserData to share
* (our UserData must always be the same as Machine's data)
*/
- mUserData.share(mPeer->mUserData);
+ mUserData.share(aMachine->mUserData);
/* allocate private copies of all other data (will be loaded from settings) */
mHWData.allocate();
mMediaData.allocate();
@@ -1131,7 +1142,8 @@ HRESULT SnapshotMachine::init(Machine *aMachine,
unconst(mUSBController).createObject();
mUSBController->init(this);
- for (ULONG slot = 0; slot < RT_ELEMENTS(mNetworkAdapters); slot++)
+ mNetworkAdapters.resize(Global::getMaxNetworkAdapters(mHWData->mChipsetType));
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
{
unconst(mNetworkAdapters[slot]).createObject();
mNetworkAdapters[slot]->init(this, slot);
@@ -1154,7 +1166,7 @@ HRESULT SnapshotMachine::init(Machine *aMachine,
/* load hardware and harddisk settings */
- HRESULT rc = loadHardware(hardware);
+ HRESULT rc = loadHardware(hardware, pDbg, pAutostart);
if (SUCCEEDED(rc))
rc = loadStorageControllers(storage,
NULL, /* puuidRegistry */
@@ -1162,7 +1174,9 @@ HRESULT SnapshotMachine::init(Machine *aMachine,
if (SUCCEEDED(rc))
/* commit all changes made during the initialization */
- commit(); // @todo r=dj why do we need a commit in init?!? this is very expensive
+ commit(); /// @todo r=dj why do we need a commit in init?!? this is very expensive
+ /// @todo r=klaus for some reason the settings loading logic backs up
+ // the settings, and therefore a commit is needed. Should probably be changed.
/* Confirm a successful initialization when it's the case */
if (SUCCEEDED(rc))
@@ -1189,6 +1203,7 @@ void SnapshotMachine::uninit()
/* free the essential data structure last */
mData.free();
+ unconst(mMachine) = NULL;
unconst(mParent) = NULL;
unconst(mPeer) = NULL;
@@ -1197,12 +1212,12 @@ void SnapshotMachine::uninit()
/**
* Overrides VirtualBoxBase::lockHandle() in order to share the lock handle
- * with the primary Machine instance (mPeer).
+ * with the primary Machine instance (mMachine) if it exists.
*/
RWLockHandle *SnapshotMachine::lockHandle() const
{
- AssertReturn(mPeer != NULL, NULL);
- return mPeer->lockHandle();
+ AssertReturn(mMachine != NULL, NULL);
+ return mMachine->lockHandle();
}
////////////////////////////////////////////////////////////////////////////////
@@ -1227,10 +1242,10 @@ HRESULT SnapshotMachine::onSnapshotChange(Snapshot *aSnapshot)
/* Flag the machine as dirty or change won't get saved. We disable the
* modification of the current state flag, cause this snapshot data isn't
* related to the current state. */
- mPeer->setModified(Machine::IsModified_Snapshots, false /* fAllowStateModification */);
- HRESULT rc = mPeer->saveSettings(&fNeedsGlobalSaveSettings,
- SaveS_Force); // we know we need saving, no need to check
- mlock.leave();
+ mMachine->setModified(Machine::IsModified_Snapshots, false /* fAllowStateModification */);
+ HRESULT rc = mMachine->saveSettings(&fNeedsGlobalSaveSettings,
+ SaveS_Force); // we know we need saving, no need to check
+ mlock.release();
if (SUCCEEDED(rc) && fNeedsGlobalSaveSettings)
{
@@ -1394,8 +1409,6 @@ STDMETHODIMP SessionMachine::BeginTakingSnapshot(IConsole *aInitiator,
AutoCaller autoCaller(this);
AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
- GuidList llRegistriesThatNeedSaving;
-
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
AssertReturn( !Global::IsOnlineOrTransient(mData->mMachineState)
@@ -1423,8 +1436,16 @@ STDMETHODIMP SessionMachine::BeginTakingSnapshot(IConsole *aInitiator,
Utf8Str strStateFilePath;
/* stateFilePath is null when the machine is not online nor saved */
if (fTakingSnapshotOnline)
- // creating a new online snapshot: then we need a fresh saved state file
- composeSavedStateFilename(strStateFilePath);
+ {
+ Bstr value;
+ HRESULT rc = GetExtraData(Bstr("VBoxInternal2/ForceTakeSnapshotWithoutState").raw(),
+ value.asOutParam());
+ if (FAILED(rc) || value != "1")
+ {
+ // creating a new online snapshot: we need a fresh saved state file
+ composeSavedStateFilename(strStateFilePath);
+ }
+ }
else if (mData->mMachineState == MachineState_Saved)
// taking an online snapshot from machine in "saved" state: then use existing state file
strStateFilePath = mSSData->strStateFilePath;
@@ -1479,18 +1500,17 @@ STDMETHODIMP SessionMachine::BeginTakingSnapshot(IConsole *aInitiator,
else
setMachineState(MachineState_Saving); /** @todo Confusing! Saving is used for both online and offline snapshots. */
+ alock.release();
/* create new differencing hard disks and attach them to this machine */
rc = createImplicitDiffs(aConsoleProgress,
1, // operation weight; must be the same as in Console::TakeSnapshot()
- !!fTakingSnapshotOnline,
- &llRegistriesThatNeedSaving);
+ !!fTakingSnapshotOnline);
if (FAILED(rc))
throw rc;
- // if we got this far without an error, then save the media registries
- // that got modified for the diff images
- alock.release();
- mParent->saveRegistries(llRegistriesThatNeedSaving);
+ // MUST NOT save the settings or the media registry here, because
+ // this causes trouble with rolling back settings if the user cancels
+ // taking the snapshot after the diff images have been created.
}
catch (HRESULT hrc)
{
@@ -1597,11 +1617,14 @@ STDMETHODIMP SessionMachine::EndTakingSnapshot(BOOL aSuccess)
/* inform callbacks */
mParent->onSnapshotTaken(mData->mUuid,
mConsoleTaskData.mSnapshot->getId());
+ machineLock.release();
}
else
{
/* delete all differencing hard disks created (this will also attach
* their parents back by rolling back mMediaData) */
+ machineLock.release();
+
rollbackMedia();
mData->mFirstSnapshot = pOldFirstSnap; // might have been changed above
@@ -1613,14 +1636,22 @@ STDMETHODIMP SessionMachine::EndTakingSnapshot(BOOL aSuccess)
// snapshot means that a new saved state file was created, which we must
// clean up now
RTFileDelete(mConsoleTaskData.mSnapshot->getStateFilePath().c_str());
+ machineLock.acquire();
+
mConsoleTaskData.mSnapshot->uninit();
+ machineLock.release();
+
}
/* clear out the snapshot data */
mConsoleTaskData.mLastState = MachineState_Null;
mConsoleTaskData.mSnapshot.setNull();
+ /* machineLock has been released already */
+
+ mParent->saveModifiedRegistries();
+
return rc;
}
@@ -1771,7 +1802,6 @@ void SessionMachine::restoreSnapshotHandler(RestoreSnapshotTask &aTask)
HRESULT rc = S_OK;
bool stateRestored = false;
- GuidList llRegistriesThatNeedSaving;
try
{
@@ -1832,18 +1862,17 @@ void SessionMachine::restoreSnapshotHandler(RestoreSnapshotTask &aTask)
mMediaData->mAttachments.push_back(pAttach);
}
- /* leave the locks before the potentially lengthy operation */
+ /* release the locks before the potentially lengthy operation */
snapshotLock.release();
- alock.leave();
+ alock.release();
rc = createImplicitDiffs(aTask.pProgress,
1,
- false /* aOnline */,
- &llRegistriesThatNeedSaving);
+ false /* aOnline */);
if (FAILED(rc))
throw rc;
- alock.enter();
+ alock.acquire();
snapshotLock.acquire();
/* Note: on success, current (old) hard disks will be
@@ -1890,8 +1919,6 @@ void SessionMachine::restoreSnapshotHandler(RestoreSnapshotTask &aTask)
}
}
- int saveFlags = 0;
-
/* we have already deleted the current state, so set the execution
* state accordingly no matter of the delete snapshot result */
if (mSSData->strStateFilePath.isNotEmpty())
@@ -1902,8 +1929,12 @@ void SessionMachine::restoreSnapshotHandler(RestoreSnapshotTask &aTask)
updateMachineStateOnClient();
stateRestored = true;
+ /* Paranoia: no one must have saved the settings in the mean time. If
+ * it happens nevertheless we'll close our eyes and continue below. */
+ Assert(mMediaData.isBackedUp());
+
/* assign the timestamp from the snapshot */
- Assert(RTTimeSpecGetMilli (&snapshotTimeStamp) != 0);
+ Assert(RTTimeSpecGetMilli(&snapshotTimeStamp) != 0);
mData->mLastStateChange = snapshotTimeStamp;
// detach the current-state diffs that we detected above and build a list of
@@ -1929,9 +1960,12 @@ void SessionMachine::restoreSnapshotHandler(RestoreSnapshotTask &aTask)
// the time in our case so instead we force a detachment here:
// remove from machine data
mMediaData->mAttachments.remove(pAttach);
- // remove it from the backup or else saveSettings will try to detach
- // it again and assert
- mMediaData.backedUpData()->mAttachments.remove(pAttach);
+ // Remove it from the backup or else saveSettings will try to detach
+ // it again and assert. The paranoia check avoids crashes (see
+ // assert above) if this code is buggy and saves settings in the
+ // wrong place.
+ if (mMediaData.isBackedUp())
+ mMediaData.backedUpData()->mAttachments.remove(pAttach);
// then clean up backrefs
pMedium->removeBackReference(mData->mUuid);
@@ -1941,15 +1975,17 @@ void SessionMachine::restoreSnapshotHandler(RestoreSnapshotTask &aTask)
// save machine settings, reset the modified flag and commit;
bool fNeedsGlobalSaveSettings = false;
rc = saveSettings(&fNeedsGlobalSaveSettings,
- SaveS_ResetCurStateModified | saveFlags);
+ SaveS_ResetCurStateModified);
if (FAILED(rc))
throw rc;
// unconditionally add the parent registry. We do similar in SessionMachine::EndTakingSnapshot
// (mParent->saveSettings())
- VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, mParent->getGlobalRegistryId());
- // let go of the locks while we're deleting image files below
- alock.leave();
+ // release the locks before updating registry and deleting image files
+ alock.release();
+
+ mParent->markRegistryModified(mParent->getGlobalRegistryId());
+
// from here on we cannot roll back on failure any more
for (MediaList::iterator it = llDiffsToDelete.begin();
@@ -1960,8 +1996,7 @@ void SessionMachine::restoreSnapshotHandler(RestoreSnapshotTask &aTask)
LogFlowThisFunc(("Deleting old current state in differencing image '%s'\n", pMedium->getName().c_str()));
HRESULT rc2 = pMedium->deleteStorage(NULL /* aProgress */,
- true /* aWait */,
- &llRegistriesThatNeedSaving);
+ true /* aWait */);
// ignore errors here because we cannot roll back after saveSettings() above
if (SUCCEEDED(rc2))
pMedium->uninit();
@@ -1988,7 +2023,7 @@ void SessionMachine::restoreSnapshotHandler(RestoreSnapshotTask &aTask)
}
}
- mParent->saveRegistries(llRegistriesThatNeedSaving);
+ mParent->saveModifiedRegistries();
/* set the result (this will try to fetch current error info on failure) */
aTask.pProgress->notifyComplete(rc);
@@ -2289,23 +2324,21 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
return;
}
- MediumDeleteRecList toDelete;
-
HRESULT rc = S_OK;
-
- GuidList llRegistriesThatNeedSaving;
-
+ MediumDeleteRecList toDelete;
Guid snapshotId;
try
{
/* Locking order: */
- AutoMultiWriteLock3 multiLock(this->lockHandle(), // machine
- aTask.pSnapshot->lockHandle(), // snapshot
- &mParent->getMediaTreeLockHandle() // media tree
+ AutoMultiWriteLock2 multiLock(this->lockHandle(), // machine
+ aTask.pSnapshot->lockHandle() // snapshot
+ COMMA_LOCKVAL_SRC_POS);
+ // once we have this lock, we know that SessionMachine::DeleteSnapshot()
+ // has exited after setting the machine state to MachineState_DeletingSnapshot
+
+ AutoWriteLock treeLock(mParent->getMediaTreeLockHandle()
COMMA_LOCKVAL_SRC_POS);
- // once we have this lock, we know that SessionMachine::DeleteSnapshot()
- // has exited after setting the machine state to MachineState_DeletingSnapshot
ComObjPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->getSnapshotMachine();
// no need to lock the snapshot machine since it is const by definition
@@ -2382,6 +2415,11 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
else
fOnlineMergePossible = false;
}
+
+ // no need to hold the lock any longer
+ attachLock.release();
+
+ treeLock.release();
rc = prepareDeleteSnapshotMedium(pHD, machineId, snapshotId,
fOnlineMergePossible,
pVMMALockList, pSource, pTarget,
@@ -2389,12 +2427,10 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
childrenToReparent,
fNeedsOnlineMerge,
pMediumLockList);
+ treeLock.acquire();
if (FAILED(rc))
throw rc;
- // no need to hold the lock any longer
- attachLock.release();
-
// For simplicity, prepareDeleteSnapshotMedium selects the merge
// direction in the following way: we merge pHD onto its child
// (forward merge), not the other way round, because that saves us
@@ -2463,7 +2499,8 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
pMediumLockList));
}
- // we can release the lock now since the machine state is MachineState_DeletingSnapshot
+ // we can release the locks now since the machine state is MachineState_DeletingSnapshot
+ treeLock.release();
multiLock.release();
/* Now we checked that we can successfully merge all normal hard disks
@@ -2490,7 +2527,8 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
releaseSavedStateFile(stateFilePath, aTask.pSnapshot /* pSnapshotToIgnore */);
// machine will need saving now
- VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, getId());
+ machineLock.release();
+ mParent->markRegistryModified(getId());
}
}
@@ -2537,8 +2575,7 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
/* No need to hold the lock any longer. */
mLock.release();
rc = pMedium->deleteStorage(&aTask.pProgress,
- true /* aWait */,
- &llRegistriesThatNeedSaving);
+ true /* aWait */);
if (FAILED(rc))
throw rc;
@@ -2571,8 +2608,7 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
it->mChildrenToReparent,
it->mpMediumLockList,
&aTask.pProgress,
- true /* aWait */,
- &llRegistriesThatNeedSaving);
+ true /* aWait */);
}
// If the merge failed, we need to do our best to have a usable
@@ -2665,7 +2701,7 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
it->mpSource->uninit();
// One attachment is merged, must save the settings
- VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, getId());
+ mParent->markRegistryModified(getId());
// prevent calling cancelDeleteSnapshotMedium() for this attachment
it = toDelete.erase(it);
@@ -2684,7 +2720,8 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
aTask.pSnapshot->beginSnapshotDelete();
aTask.pSnapshot->uninit();
- VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, getId());
+ machineLock.release();
+ mParent->markRegistryModified(getId());
}
}
catch (HRESULT aRC) { rc = aRC; }
@@ -2724,7 +2761,7 @@ void SessionMachine::deleteSnapshotHandler(DeleteSnapshotTask &aTask)
setMachineState(aTask.machineStateBackup);
updateMachineStateOnClient();
- mParent->saveRegistries(llRegistriesThatNeedSaving);
+ mParent->saveModifiedRegistries();
}
// report the result (this will try to fetch current error info on failure)
@@ -2784,7 +2821,7 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
bool &fNeedsOnlineMerge,
MediumLockList * &aMediumLockList)
{
- Assert(mParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
+ Assert(!mParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
Assert(!fOnlineMergePossible || VALID_PTR(aVMMALockList));
AutoWriteLock alock(aHD COMMA_LOCKVAL_SRC_POS);
@@ -2810,6 +2847,7 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
{
/* lock only, to prevent any usage until the snapshot deletion
* is completed */
+ alock.release();
return aHD->LockWrite(NULL);
}
@@ -2827,8 +2865,6 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
ComObjPtr<Medium> pChild = aHD->getChildren().front();
- /* we keep this locked, so lock the affected child to make sure the lock
- * order is correct when calling prepareMergeTo() */
AutoWriteLock childLock(pChild COMMA_LOCKVAL_SRC_POS);
/* the rest is a normal merge setup */
@@ -2841,6 +2877,8 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
{
/* backward merge is too tricky, we'll just detach on snapshot
* deletion, so lock only, to prevent any usage */
+ childLock.release();
+ alock.release();
return aHD->LockWrite(NULL);
}
@@ -2855,17 +2893,25 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
}
HRESULT rc;
+ childLock.release();
+ alock.release();
rc = aSource->prepareMergeTo(aTarget, &aMachineId, &aSnapshotId,
!fOnlineMergePossible /* fLockMedia */,
aMergeForward, aParentForTarget,
aChildrenToReparent, aMediumLockList);
+ alock.acquire();
+ childLock.acquire();
if (SUCCEEDED(rc) && fOnlineMergePossible)
{
/* Try to lock the newly constructed medium lock list. If it succeeds
* this can be handled as an offline merge, i.e. without the need of
* asking the VM to do the merging. Only continue with the online
* merging preparation if applicable. */
+ childLock.release();
+ alock.release();
rc = aMediumLockList->Lock();
+ alock.acquire();
+ childLock.acquire();
if (FAILED(rc) && fOnlineMergePossible)
{
/* Locking failed, this cannot be done as an offline merge. Try to
@@ -2893,7 +2939,11 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
break;
}
bool fLockReq = (it2->GetLockRequest() || it->GetLockRequest());
+ childLock.release();
+ alock.release();
rc = it->UpdateLock(fLockReq);
+ alock.acquire();
+ childLock.acquire();
if (FAILED(rc))
{
// could not update the lock, trigger cleanup below
@@ -2910,20 +2960,39 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
++it)
{
ComObjPtr<Medium> pMedium = *it;
+ AutoReadLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS);
if (pMedium->getState() == MediumState_Created)
{
+ mediumLock.release();
+ childLock.release();
+ alock.release();
rc = pMedium->LockWrite(NULL);
+ alock.acquire();
+ childLock.acquire();
+ mediumLock.acquire();
if (FAILED(rc))
throw rc;
}
else
{
+ mediumLock.release();
+ childLock.release();
+ alock.release();
rc = aVMMALockList->Update(pMedium, true);
+ alock.acquire();
+ childLock.acquire();
+ mediumLock.acquire();
if (FAILED(rc))
{
+ mediumLock.release();
+ childLock.release();
+ alock.release();
rc = pMedium->LockWrite(NULL);
+ alock.acquire();
+ childLock.acquire();
+ mediumLock.acquire();
if (FAILED(rc))
- throw rc;
+ throw rc;
}
}
}
@@ -2931,7 +3000,11 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
if (fOnlineMergePossible)
{
+ childLock.release();
+ alock.release();
rc = aVMMALockList->Lock();
+ alock.acquire();
+ childLock.acquire();
if (FAILED(rc))
{
aSource->cancelMergeTo(aChildrenToReparent, aMediumLockList);
@@ -2965,7 +3038,11 @@ HRESULT SessionMachine::prepareDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD
it != lockListVMMAEnd;
++it)
{
+ childLock.release();
+ alock.release();
it->UpdateLock(it == lockListLast);
+ alock.acquire();
+ childLock.acquire();
ComObjPtr<Medium> pMedium = it->GetMedium();
AutoWriteLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS);
// blindly apply this, only needed for medium objects which
@@ -3056,7 +3133,9 @@ void SessionMachine::cancelDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD,
// would be deleted as part of the merge
pMedium->unmarkLockedForDeletion();
}
+ mediumLock.release();
it->UpdateLock(it == lockListLast);
+ mediumLock.acquire();
}
}
else
@@ -3220,7 +3299,7 @@ STDMETHODIMP SessionMachine::FinishOnlineMergeMedium(IMediumAttachment *aMediumA
{
// first, unregister the target since it may become a base
// hard disk which needs re-registration
- rc = mParent->unregisterMedium(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
+ rc = mParent->unregisterMedium(pTarget);
AssertComRC(rc);
// then, reparent it and disconnect the deleted branch at
@@ -3231,7 +3310,7 @@ STDMETHODIMP SessionMachine::FinishOnlineMergeMedium(IMediumAttachment *aMediumA
pSource->deparent();
// then, register again
- rc = mParent->registerMedium(pTarget, &pTarget, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */);
+ rc = mParent->registerMedium(pTarget, &pTarget, DeviceType_HardDisk);
AssertComRC(rc);
}
else
@@ -3259,7 +3338,9 @@ STDMETHODIMP SessionMachine::FinishOnlineMergeMedium(IMediumAttachment *aMediumA
Medium *pMedium = static_cast<Medium *>(childrenToReparent[i]);
toReparent.push_back(pMedium);
}
+ treeLock.release();
pTarget->fixParentUuidOfChildren(toReparent);
+ treeLock.acquire();
// obey {parent,child} lock order
AutoWriteLock sourceLock(pSource COMMA_LOCKVAL_SRC_POS);
@@ -3302,7 +3383,7 @@ STDMETHODIMP SessionMachine::FinishOnlineMergeMedium(IMediumAttachment *aMediumA
}
else
{
- rc = mParent->unregisterMedium(pMedium, NULL /* pllRegistriesThatNeedSaving */);
+ rc = mParent->unregisterMedium(pMedium);
AssertComRC(rc);
/* now, uninitialize the deleted hard disk (note that
diff --git a/src/VBox/Main/src-server/StorageControllerImpl.cpp b/src/VBox/Main/src-server/StorageControllerImpl.cpp
index 5390b5fa2..100c5b227 100644
--- a/src/VBox/Main/src-server/StorageControllerImpl.cpp
+++ b/src/VBox/Main/src-server/StorageControllerImpl.cpp
@@ -640,10 +640,10 @@ STDMETHODIMP StorageController::COMGETTER(Bootable) (BOOL *fBootable)
return S_OK;
}
-// IStorageController methods
+// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP StorageController::GetIDEEmulationPort(LONG DevicePosition, LONG *aPortNumber)
+HRESULT StorageController::getIDEEmulationPort(LONG DevicePosition, LONG *aPortNumber)
{
CheckComArgOutPointerValid(aPortNumber);
@@ -677,7 +677,7 @@ STDMETHODIMP StorageController::GetIDEEmulationPort(LONG DevicePosition, LONG *a
return S_OK;
}
-STDMETHODIMP StorageController::SetIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
+HRESULT StorageController::setIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -717,10 +717,6 @@ STDMETHODIMP StorageController::SetIDEEmulationPort(LONG DevicePosition, LONG aP
return S_OK;
}
-// public methods only for internal purposes
-/////////////////////////////////////////////////////////////////////////////
-
-
const Utf8Str& StorageController::getName() const
{
return m->bd->strName;
diff --git a/src/VBox/Main/src-server/SystemPropertiesImpl.cpp b/src/VBox/Main/src-server/SystemPropertiesImpl.cpp
index 8acdede9b..380f7574b 100644
--- a/src/VBox/Main/src-server/SystemPropertiesImpl.cpp
+++ b/src/VBox/Main/src-server/SystemPropertiesImpl.cpp
@@ -1,12 +1,10 @@
/* $Id: SystemPropertiesImpl.cpp $ */
-
/** @file
- *
* VirtualBox COM class implementation
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -26,6 +24,7 @@
#include "AutoCaller.h"
#include "Global.h"
#include "Logging.h"
+#include "AutostartDb.h"
// generated header
#include "SchemaDefs.h"
@@ -321,20 +320,10 @@ STDMETHODIMP SystemProperties::GetMaxNetworkAdapters(ChipsetType_T aChipset, ULO
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- ULONG uResult = 0;
-
/* no need for locking, no state */
- switch (aChipset)
- {
- case ChipsetType_PIIX3:
- uResult = SchemaDefs::NetworkAdapterCount; /* == 8 */
- break;
- case ChipsetType_ICH9:
- uResult = 36;
- break;
- default:
- AssertMsgFailed(("Invalid chipset type %d\n", aChipset));
- }
+ uint32_t uResult = Global::getMaxNetworkAdapters(aChipset);
+ if (uResult == 0)
+ AssertMsgFailed(("Invalid chipset type %d\n", aChipset));
*count = uResult;
@@ -348,12 +337,11 @@ STDMETHODIMP SystemProperties::GetMaxNetworkAdaptersOfType(ChipsetType_T aChipse
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- ULONG uResult = 0;
- HRESULT rc = GetMaxNetworkAdapters(aChipset, &uResult);
- if (FAILED(rc))
- return rc;
-
/* no need for locking, no state */
+ uint32_t uResult = Global::getMaxNetworkAdapters(aChipset);
+ if (uResult == 0)
+ AssertMsgFailed(("Invalid chipset type %d\n", aChipset));
+
switch (aType)
{
case NetworkAttachmentType_NAT:
@@ -364,7 +352,7 @@ STDMETHODIMP SystemProperties::GetMaxNetworkAdaptersOfType(ChipsetType_T aChipse
/* Maybe use current host interface count here? */
break;
case NetworkAttachmentType_HostOnly:
- uResult = 8;
+ uResult = RT_MIN(uResult, 8);
break;
default:
AssertMsgFailed(("Unhandled attachment type %d\n", aType));
@@ -929,6 +917,86 @@ STDMETHODIMP SystemProperties::COMGETTER(DefaultAudioDriver)(AudioDriverType_T *
return S_OK;
}
+STDMETHODIMP SystemProperties::COMGETTER(AutostartDatabasePath)(BSTR *aAutostartDbPath)
+{
+ CheckComArgOutPointerValid(aAutostartDbPath);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ m->strAutostartDatabasePath.cloneTo(aAutostartDbPath);
+
+ return S_OK;
+}
+
+STDMETHODIMP SystemProperties::COMSETTER(AutostartDatabasePath)(IN_BSTR aAutostartDbPath)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ HRESULT rc = setAutostartDatabasePath(aAutostartDbPath);
+ alock.release();
+
+ if (SUCCEEDED(rc))
+ {
+ // VirtualBox::saveSettings() needs vbox write lock
+ AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
+ rc = mParent->saveSettings();
+ }
+
+ return rc;
+}
+
+STDMETHODIMP SystemProperties::COMGETTER(DefaultAdditionsISO)(BSTR *aDefaultAdditionsISO)
+{
+ CheckComArgOutPointerValid(aDefaultAdditionsISO);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ if (m->strDefaultAdditionsISO.isEmpty())
+ {
+ /* no guest additions, check if it showed up in the mean time */
+ alock.release();
+ {
+ AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
+ ErrorInfoKeeper eik;
+ (void)setDefaultAdditionsISO("");
+ }
+ alock.acquire();
+ }
+ m->strDefaultAdditionsISO.cloneTo(aDefaultAdditionsISO);
+
+ return S_OK;
+}
+
+STDMETHODIMP SystemProperties::COMSETTER(DefaultAdditionsISO)(IN_BSTR aDefaultAdditionsISO)
+{
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ /** @todo not yet implemented, settings handling is missing */
+ ReturnComNotImplemented();
+
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ HRESULT rc = setDefaultAdditionsISO(aDefaultAdditionsISO);
+ alock.release();
+
+ if (SUCCEEDED(rc))
+ {
+ // VirtualBox::saveSettings() needs vbox write lock
+ AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
+ rc = mParent->saveSettings();
+ }
+
+ return rc;
+}
+
// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
@@ -958,6 +1026,16 @@ HRESULT SystemProperties::loadSettings(const settings::SystemProperties &data)
m->ulLogHistoryCount = data.ulLogHistoryCount;
+ rc = setAutostartDatabasePath(data.strAutostartDatabasePath);
+ if (FAILED(rc)) return rc;
+
+ {
+ /* must ignore errors signalled here, because the guest additions
+ * file may not exist, and in this case keep the empty string */
+ ErrorInfoKeeper eik;
+ (void)setDefaultAdditionsISO(data.strDefaultAdditionsISO);
+ }
+
return S_OK;
}
@@ -1135,3 +1213,78 @@ HRESULT SystemProperties::setDefaultVRDEExtPack(const Utf8Str &aExtPack)
return S_OK;
}
+
+HRESULT SystemProperties::setAutostartDatabasePath(const Utf8Str &aPath)
+{
+ HRESULT rc = S_OK;
+ AutostartDb *autostartDb = this->mParent->getAutostartDb();
+
+ if (!aPath.isEmpty())
+ {
+ /* Update path in the autostart database. */
+ int vrc = autostartDb->setAutostartDbPath(aPath.c_str());
+ if (RT_SUCCESS(vrc))
+ m->strAutostartDatabasePath = aPath;
+ else
+ rc = setError(E_FAIL,
+ tr("Cannot set the autostart database path (%Rrc)"),
+ vrc);
+ }
+ else
+ {
+ int vrc = autostartDb->setAutostartDbPath(NULL);
+ if (RT_SUCCESS(vrc) || vrc == VERR_NOT_SUPPORTED)
+ m->strAutostartDatabasePath = "";
+ else
+ rc = setError(E_FAIL,
+ tr("Deleting the autostart database path failed (%Rrc)"),
+ vrc);
+ }
+
+ return rc;
+}
+
+HRESULT SystemProperties::setDefaultAdditionsISO(const Utf8Str &aPath)
+{
+ Utf8Str path(aPath);
+ if (path.isEmpty())
+ {
+ char strTemp[RTPATH_MAX];
+ int vrc = RTPathAppPrivateNoArch(strTemp, sizeof(strTemp));
+ AssertRC(vrc);
+ Utf8Str strSrc1 = Utf8Str(strTemp).append("/VBoxGuestAdditions.iso");
+
+ vrc = RTPathExecDir(strTemp, sizeof(strTemp));
+ AssertRC(vrc);
+ Utf8Str strSrc2 = Utf8Str(strTemp).append("/additions/VBoxGuestAdditions.iso");
+
+ vrc = RTPathUserHome(strTemp, sizeof(strTemp));
+ AssertRC(vrc);
+ Utf8Str strSrc3 = Utf8StrFmt("%s/VBoxGuestAdditions_%ls.iso", strTemp, VirtualBox::getVersionNormalized().raw());
+
+ /* Check the standard image locations */
+ if (RTFileExists(strSrc1.c_str()))
+ path = strSrc1;
+ else if (RTFileExists(strSrc2.c_str()))
+ path = strSrc2;
+ else if (RTFileExists(strSrc3.c_str()))
+ path = strSrc3;
+ else
+ return setError(E_FAIL,
+ tr("Cannot determine default Guest Additions ISO location. Most likely they are not available"));
+ }
+
+ if (!RTPathStartsWithRoot(path.c_str()))
+ return setError(E_INVALIDARG,
+ tr("Given default machine Guest Additions ISO file '%s' is not fully qualified"),
+ path.c_str());
+
+ if (!RTFileExists(path.c_str()))
+ return setError(E_INVALIDARG,
+ tr("Given default machine Guest Additions ISO file '%s' does not exist"),
+ path.c_str());
+
+ m->strDefaultAdditionsISO = path;
+
+ return S_OK;
+}
diff --git a/src/VBox/Main/src-server/USBControllerImpl.cpp b/src/VBox/Main/src-server/USBControllerImpl.cpp
index 624e02a5a..8f4d1c483 100644
--- a/src/VBox/Main/src-server/USBControllerImpl.cpp
+++ b/src/VBox/Main/src-server/USBControllerImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -85,7 +85,7 @@ struct USBController::Data
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
-DEFINE_EMPTY_CTOR_DTOR (USBController)
+DEFINE_EMPTY_CTOR_DTOR(USBController)
HRESULT USBController::FinalConstruct()
{
@@ -171,7 +171,7 @@ HRESULT USBController::init(Machine *aParent, USBController *aPeer)
filter.createObject();
filter->init(this, *it);
m->llDeviceFilters->push_back(filter);
- ++ it;
+ ++it;
}
#endif /* VBOX_WITH_USB */
@@ -214,7 +214,7 @@ HRESULT USBController::initCopy(Machine *aParent, USBController *aPeer)
filter.createObject();
filter->initCopy(this, *it);
m->llDeviceFilters->push_back(filter);
- ++ it;
+ ++it;
}
#endif /* VBOX_WITH_USB */
@@ -261,7 +261,7 @@ void USBController::uninit()
// IUSBController properties
/////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP USBController::COMGETTER(Enabled) (BOOL *aEnabled)
+STDMETHODIMP USBController::COMGETTER(Enabled)(BOOL *aEnabled)
{
CheckComArgOutPointerValid(aEnabled);
@@ -276,7 +276,7 @@ STDMETHODIMP USBController::COMGETTER(Enabled) (BOOL *aEnabled)
}
-STDMETHODIMP USBController::COMSETTER(Enabled) (BOOL aEnabled)
+STDMETHODIMP USBController::COMSETTER(Enabled)(BOOL aEnabled)
{
LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
@@ -307,7 +307,7 @@ STDMETHODIMP USBController::COMSETTER(Enabled) (BOOL aEnabled)
return S_OK;
}
-STDMETHODIMP USBController::COMGETTER(EnabledEhci) (BOOL *aEnabled)
+STDMETHODIMP USBController::COMGETTER(EnabledEHCI)(BOOL *aEnabled)
{
CheckComArgOutPointerValid(aEnabled);
@@ -321,7 +321,7 @@ STDMETHODIMP USBController::COMGETTER(EnabledEhci) (BOOL *aEnabled)
return S_OK;
}
-STDMETHODIMP USBController::COMSETTER(EnabledEhci) (BOOL aEnabled)
+STDMETHODIMP USBController::COMSETTER(EnabledEHCI)(BOOL aEnabled)
{
LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
@@ -352,7 +352,7 @@ STDMETHODIMP USBController::COMSETTER(EnabledEhci) (BOOL aEnabled)
return S_OK;
}
-STDMETHODIMP USBController::COMGETTER(ProxyAvailable) (BOOL *aEnabled)
+STDMETHODIMP USBController::COMGETTER(ProxyAvailable)(BOOL *aEnabled)
{
CheckComArgOutPointerValid(aEnabled);
@@ -370,7 +370,7 @@ STDMETHODIMP USBController::COMGETTER(ProxyAvailable) (BOOL *aEnabled)
return S_OK;
}
-STDMETHODIMP USBController::COMGETTER(USBStandard) (USHORT *aUSBStandard)
+STDMETHODIMP USBController::COMGETTER(USBStandard)(USHORT *aUSBStandard)
{
CheckComArgOutPointerValid(aUSBStandard);
@@ -398,50 +398,49 @@ public:
DECLARE_NOT_AGGREGATABLE(USBDeviceFilter)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(USBDeviceFilter)
- COM_INTERFACE_ENTRY(ISupportErrorInfo)
- COM_INTERFACE_ENTRY(IUSBDeviceFilter)
+ VBOX_DEFAULT_INTERFACE_ENTRIES(IUSBDeviceFilter)
END_COM_MAP()
- DECLARE_EMPTY_CTOR_DTOR (USBDeviceFilter)
+ DECLARE_EMPTY_CTOR_DTOR(USBDeviceFilter)
// IUSBDeviceFilter properties
- STDMETHOD(COMGETTER(Name)) (BSTR *aName);
- STDMETHOD(COMSETTER(Name)) (IN_BSTR aName);
- STDMETHOD(COMGETTER(Active)) (BOOL *aActive);
- STDMETHOD(COMSETTER(Active)) (BOOL aActive);
- STDMETHOD(COMGETTER(VendorId)) (BSTR *aVendorId);
- STDMETHOD(COMSETTER(VendorId)) (IN_BSTR aVendorId);
- STDMETHOD(COMGETTER(ProductId)) (BSTR *aProductId);
- STDMETHOD(COMSETTER(ProductId)) (IN_BSTR aProductId);
- STDMETHOD(COMGETTER(Revision)) (BSTR *aRevision);
- STDMETHOD(COMSETTER(Revision)) (IN_BSTR aRevision);
- STDMETHOD(COMGETTER(Manufacturer)) (BSTR *aManufacturer);
- STDMETHOD(COMSETTER(Manufacturer)) (IN_BSTR aManufacturer);
- STDMETHOD(COMGETTER(Product)) (BSTR *aProduct);
- STDMETHOD(COMSETTER(Product)) (IN_BSTR aProduct);
- STDMETHOD(COMGETTER(SerialNumber)) (BSTR *aSerialNumber);
- STDMETHOD(COMSETTER(SerialNumber)) (IN_BSTR aSerialNumber);
- STDMETHOD(COMGETTER(Port)) (BSTR *aPort);
- STDMETHOD(COMSETTER(Port)) (IN_BSTR aPort);
- STDMETHOD(COMGETTER(Remote)) (BSTR *aRemote);
- STDMETHOD(COMSETTER(Remote)) (IN_BSTR aRemote);
- STDMETHOD(COMGETTER(MaskedInterfaces)) (ULONG *aMaskedIfs);
- STDMETHOD(COMSETTER(MaskedInterfaces)) (ULONG aMaskedIfs);
+ STDMETHOD(COMGETTER(Name))(BSTR *aName);
+ STDMETHOD(COMSETTER(Name))(IN_BSTR aName);
+ STDMETHOD(COMGETTER(Active))(BOOL *aActive);
+ STDMETHOD(COMSETTER(Active))(BOOL aActive);
+ STDMETHOD(COMGETTER(VendorId))(BSTR *aVendorId);
+ STDMETHOD(COMSETTER(VendorId))(IN_BSTR aVendorId);
+ STDMETHOD(COMGETTER(ProductId))(BSTR *aProductId);
+ STDMETHOD(COMSETTER(ProductId))(IN_BSTR aProductId);
+ STDMETHOD(COMGETTER(Revision))(BSTR *aRevision);
+ STDMETHOD(COMSETTER(Revision))(IN_BSTR aRevision);
+ STDMETHOD(COMGETTER(Manufacturer))(BSTR *aManufacturer);
+ STDMETHOD(COMSETTER(Manufacturer))(IN_BSTR aManufacturer);
+ STDMETHOD(COMGETTER(Product))(BSTR *aProduct);
+ STDMETHOD(COMSETTER(Product))(IN_BSTR aProduct);
+ STDMETHOD(COMGETTER(SerialNumber))(BSTR *aSerialNumber);
+ STDMETHOD(COMSETTER(SerialNumber))(IN_BSTR aSerialNumber);
+ STDMETHOD(COMGETTER(Port))(BSTR *aPort);
+ STDMETHOD(COMSETTER(Port))(IN_BSTR aPort);
+ STDMETHOD(COMGETTER(Remote))(BSTR *aRemote);
+ STDMETHOD(COMSETTER(Remote))(IN_BSTR aRemote);
+ STDMETHOD(COMGETTER(MaskedInterfaces))(ULONG *aMaskedIfs);
+ STDMETHOD(COMSETTER(MaskedInterfaces))(ULONG aMaskedIfs);
};
#endif /* !VBOX_WITH_USB */
-STDMETHODIMP USBController::COMGETTER(DeviceFilters) (ComSafeArrayOut(IUSBDeviceFilter *, aDevicesFilters))
+STDMETHODIMP USBController::COMGETTER(DeviceFilters)(ComSafeArrayOut(IUSBDeviceFilter *, aDevicesFilters))
{
#ifdef VBOX_WITH_USB
CheckComArgOutSafeArrayPointerValid(aDevicesFilters);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if(FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- SafeIfaceArray<IUSBDeviceFilter> collection (*m->llDeviceFilters.data());
+ SafeIfaceArray<IUSBDeviceFilter> collection(*m->llDeviceFilters.data());
collection.detachTo(ComSafeArrayOutArg(aDevicesFilters));
return S_OK;
@@ -457,8 +456,8 @@ STDMETHODIMP USBController::COMGETTER(DeviceFilters) (ComSafeArrayOut(IUSBDevice
// IUSBController methods
/////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP USBController::CreateDeviceFilter (IN_BSTR aName,
- IUSBDeviceFilter **aFilter)
+STDMETHODIMP USBController::CreateDeviceFilter(IN_BSTR aName,
+ IUSBDeviceFilter **aFilter)
{
#ifdef VBOX_WITH_USB
CheckComArgOutPointerValid(aFilter);
@@ -476,8 +475,8 @@ STDMETHODIMP USBController::CreateDeviceFilter (IN_BSTR aName,
ComObjPtr<USBDeviceFilter> filter;
filter.createObject();
- HRESULT rc = filter->init (this, aName);
- ComAssertComRCRetRC (rc);
+ HRESULT rc = filter->init(this, aName);
+ ComAssertComRCRetRC(rc);
rc = filter.queryInterfaceTo(aFilter);
AssertComRCReturnRC(rc);
@@ -508,8 +507,8 @@ STDMETHODIMP USBController::InsertDeviceFilter(ULONG aPosition,
ComObjPtr<USBDeviceFilter> filter = static_cast<USBDeviceFilter*>(aFilter);
// @todo r=dj make sure the input object is actually from us
// if (!filter)
-// return setError (E_INVALIDARG,
-// tr ("The given USB device filter is not created within "
+// return setError(E_INVALIDARG,
+// tr("The given USB device filter is not created within "
// "this VirtualBox instance"));
if (filter->mInList)
@@ -524,23 +523,23 @@ STDMETHODIMP USBController::InsertDeviceFilter(ULONG aPosition,
if (aPosition < m->llDeviceFilters->size())
{
it = m->llDeviceFilters->begin();
- std::advance (it, aPosition);
+ std::advance(it, aPosition);
}
else
it = m->llDeviceFilters->end();
/* ...and insert */
- m->llDeviceFilters->insert (it, filter);
+ m->llDeviceFilters->insert(it, filter);
filter->mInList = true;
/* notify the proxy (only when it makes sense) */
if (filter->getData().mActive && Global::IsOnline(adep.machineState())
- && filter->getData().mRemote.isMatch (false))
+ && filter->getData().mRemote.isMatch(false))
{
USBProxyService *service = m->pHost->usbProxyService();
ComAssertRet(service, E_FAIL);
ComAssertRet(filter->getId() == NULL, E_FAIL);
- filter->getId() = service->insertFilter (&filter->getData().mUSBFilter);
+ filter->getId() = service->insertFilter(&filter->getData().mUSBFilter);
}
alock.release();
@@ -591,12 +590,12 @@ STDMETHODIMP USBController::RemoveDeviceFilter(ULONG aPosition,
{
/* iterate to the position... */
DeviceFilterList::iterator it = m->llDeviceFilters->begin();
- std::advance (it, aPosition);
+ std::advance(it, aPosition);
/* ...get an element from there... */
filter = *it;
/* ...and remove */
filter->mInList = false;
- m->llDeviceFilters->erase (it);
+ m->llDeviceFilters->erase(it);
}
/* cancel sharing (make an independent copy of data) */
@@ -606,7 +605,7 @@ STDMETHODIMP USBController::RemoveDeviceFilter(ULONG aPosition,
/* notify the proxy (only when it makes sense) */
if (filter->getData().mActive && Global::IsOnline(adep.machineState())
- && filter->getData().mRemote.isMatch (false))
+ && filter->getData().mRemote.isMatch(false))
{
USBProxyService *service = m->pHost->usbProxyService();
ComAssertRet(service, E_FAIL);
@@ -718,15 +717,15 @@ HRESULT USBController::saveSettings(settings::USBController &data)
f.strVendorId = str;
(*it)->COMGETTER(ProductId)(str.asOutParam());
f.strProductId = str;
- (*it)->COMGETTER (Revision) (str.asOutParam());
+ (*it)->COMGETTER(Revision)(str.asOutParam());
f.strRevision = str;
- (*it)->COMGETTER (Manufacturer) (str.asOutParam());
+ (*it)->COMGETTER(Manufacturer)(str.asOutParam());
f.strManufacturer = str;
- (*it)->COMGETTER (Product) (str.asOutParam());
+ (*it)->COMGETTER(Product)(str.asOutParam());
f.strProduct = str;
- (*it)->COMGETTER (SerialNumber) (str.asOutParam());
+ (*it)->COMGETTER(SerialNumber)(str.asOutParam());
f.strSerialNumber = str;
- (*it)->COMGETTER (Port) (str.asOutParam());
+ (*it)->COMGETTER(Port)(str.asOutParam());
f.strPort = str;
f.strRemote = filterData.mRemote.string();
f.ulMaskedInterfaces = filterData.mMaskedIfs;
@@ -764,13 +763,13 @@ void USBController::rollback()
DeviceFilterList *backedList = m->llDeviceFilters.backedUpData();
while (it != m->llDeviceFilters->end())
{
- if (std::find (backedList->begin(), backedList->end(), *it) ==
+ if (std::find(backedList->begin(), backedList->end(), *it) ==
backedList->end())
{
/* notify the proxy (only when it makes sense) */
if ((*it)->getData().mActive &&
- Global::IsOnline (adep.machineState())
- && (*it)->getData().mRemote.isMatch (false))
+ Global::IsOnline(adep.machineState())
+ && (*it)->getData().mRemote.isMatch(false))
{
USBDeviceFilter *filter = *it;
Assert(filter->getId() != NULL);
@@ -780,29 +779,29 @@ void USBController::rollback()
(*it)->uninit();
}
- ++ it;
+ ++it;
}
- if (Global::IsOnline (adep.machineState()))
+ if (Global::IsOnline(adep.machineState()))
{
/* find all removed old filters (absent in the new list)
* and insert them back to the USB proxy */
it = backedList->begin();
while (it != backedList->end())
{
- if (std::find (m->llDeviceFilters->begin(), m->llDeviceFilters->end(), *it) ==
+ if (std::find(m->llDeviceFilters->begin(), m->llDeviceFilters->end(), *it) ==
m->llDeviceFilters->end())
{
/* notify the proxy (only when necessary) */
if ((*it)->getData().mActive
- && (*it)->getData().mRemote.isMatch (false))
+ && (*it)->getData().mRemote.isMatch(false))
{
USBDeviceFilter *flt = *it; /* resolve ambiguity */
Assert(flt->getId() == NULL);
flt->getId() = service->insertFilter(&flt->getData().mUSBFilter);
}
}
- ++ it;
+ ++it;
}
}
@@ -837,11 +836,11 @@ void USBController::commit()
{
/* sanity */
AutoCaller autoCaller(this);
- AssertComRCReturnVoid (autoCaller.rc());
+ AssertComRCReturnVoid(autoCaller.rc());
/* sanity too */
AutoCaller peerCaller(m->pPeer);
- AssertComRCReturnVoid (peerCaller.rc());
+ AssertComRCReturnVoid(peerCaller.rc());
/* lock both for writing since we modify both (mPeer is "master" so locked
* first) */
@@ -893,9 +892,9 @@ void USBController::commit()
m->pPeer->m->llDeviceFilters->remove(peer);
}
/* and add it to the new list */
- newList->push_back (peer);
+ newList->push_back(peer);
- ++ it;
+ ++it;
}
/* uninit old peer's filters that are left */
@@ -903,7 +902,7 @@ void USBController::commit()
while (it != m->pPeer->m->llDeviceFilters->end())
{
(*it)->uninit();
- ++ it;
+ ++it;
}
/* attach new list of filters to our peer */
@@ -929,7 +928,7 @@ void USBController::commit()
while (it != m->llDeviceFilters->end())
{
(*it)->commit();
- ++ it;
+ ++it;
}
}
#endif /* VBOX_WITH_USB */
@@ -939,23 +938,23 @@ void USBController::commit()
* @note Locks this object for writing, together with the peer object
* represented by @a aThat (locked for reading).
*/
-void USBController::copyFrom (USBController *aThat)
+void USBController::copyFrom(USBController *aThat)
{
- AssertReturnVoid (aThat != NULL);
+ AssertReturnVoid(aThat != NULL);
/* sanity */
AutoCaller autoCaller(this);
- AssertComRCReturnVoid (autoCaller.rc());
+ AssertComRCReturnVoid(autoCaller.rc());
/* sanity too */
- AutoCaller thatCaller (aThat);
- AssertComRCReturnVoid (thatCaller.rc());
+ AutoCaller thatCaller(aThat);
+ AssertComRCReturnVoid(thatCaller.rc());
/* even more sanity */
AutoAnyStateDependency adep(m->pParent);
- AssertComRCReturnVoid (adep.rc());
+ AssertComRCReturnVoid(adep.rc());
/* Machine::copyFrom() may not be called when the VM is running */
- AssertReturnVoid (!Global::IsOnline (adep.machineState()));
+ AssertReturnVoid(!Global::IsOnline(adep.machineState()));
/* peer is not modified, lock it for reading (aThat is "master" so locked
* first) */
@@ -975,12 +974,12 @@ void USBController::copyFrom (USBController *aThat)
m->llDeviceFilters->clear();
for (DeviceFilterList::const_iterator it = aThat->m->llDeviceFilters->begin();
it != aThat->m->llDeviceFilters->end();
- ++ it)
+ ++it)
{
ComObjPtr<USBDeviceFilter> filter;
filter.createObject();
- filter->initCopy (this, *it);
- m->llDeviceFilters->push_back (filter);
+ filter->initCopy(this, *it);
+ m->llDeviceFilters->push_back(filter);
}
#endif /* VBOX_WITH_USB */
@@ -993,8 +992,8 @@ void USBController::copyFrom (USBController *aThat)
*
* @note Locks nothing.
*/
-HRESULT USBController::onDeviceFilterChange (USBDeviceFilter *aFilter,
- BOOL aActiveChanged /* = FALSE */)
+HRESULT USBController::onDeviceFilterChange(USBDeviceFilter *aFilter,
+ BOOL aActiveChanged /* = FALSE */)
{
AutoCaller autoCaller(this);
AssertComRCReturnRC(autoCaller.rc());
@@ -1004,7 +1003,7 @@ HRESULT USBController::onDeviceFilterChange (USBDeviceFilter *aFilter,
AssertComRCReturnRC(adep.rc());
/* nothing to do if the machine isn't running */
- if (!Global::IsOnline (adep.machineState()))
+ if (!Global::IsOnline(adep.machineState()))
return S_OK;
/* we don't modify our data fields -- no need to lock */
@@ -1017,7 +1016,7 @@ HRESULT USBController::onDeviceFilterChange (USBDeviceFilter *aFilter,
if (aActiveChanged)
{
- if (aFilter->getData().mRemote.isMatch (false))
+ if (aFilter->getData().mRemote.isMatch(false))
{
/* insert/remove the filter from the proxy */
if (aFilter->getData().mActive)
@@ -1040,7 +1039,7 @@ HRESULT USBController::onDeviceFilterChange (USBDeviceFilter *aFilter,
/* update the filter in the proxy */
ComAssertRet(aFilter->getId() != NULL, E_FAIL);
service->removeFilter(aFilter->getId());
- if (aFilter->getData().mRemote.isMatch (false))
+ if (aFilter->getData().mRemote.isMatch(false))
{
aFilter->getId() = service->insertFilter(&aFilter->getData().mUSBFilter);
}
@@ -1059,10 +1058,10 @@ HRESULT USBController::onDeviceFilterChange (USBDeviceFilter *aFilter,
*
* @note Locks this object for reading.
*/
-bool USBController::hasMatchingFilter (const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs)
+bool USBController::hasMatchingFilter(const ComObjPtr<HostUSBDevice> &aDevice, ULONG *aMaskedIfs)
{
AutoCaller autoCaller(this);
- AssertComRCReturn (autoCaller.rc(), false);
+ AssertComRCReturn(autoCaller.rc(), false);
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -1073,7 +1072,7 @@ bool USBController::hasMatchingFilter (const ComObjPtr<HostUSBDevice> &aDevice,
/* apply self filters */
for (DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
it != m->llDeviceFilters->end();
- ++ it)
+ ++it)
{
AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS);
if (aDevice->isMatch((*it)->getData()))
@@ -1098,12 +1097,12 @@ bool USBController::hasMatchingFilter (const ComObjPtr<HostUSBDevice> &aDevice,
*
* @note Locks this object for reading.
*/
-bool USBController::hasMatchingFilter (IUSBDevice *aUSBDevice, ULONG *aMaskedIfs)
+bool USBController::hasMatchingFilter(IUSBDevice *aUSBDevice, ULONG *aMaskedIfs)
{
LogFlowThisFuncEnter();
AutoCaller autoCaller(this);
- AssertComRCReturn (autoCaller.rc(), false);
+ AssertComRCReturn(autoCaller.rc(), false);
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -1115,50 +1114,50 @@ bool USBController::hasMatchingFilter (IUSBDevice *aUSBDevice, ULONG *aMaskedIfs
/* query fields */
USBFILTER dev;
- USBFilterInit (&dev, USBFILTERTYPE_CAPTURE);
+ USBFilterInit(&dev, USBFILTERTYPE_CAPTURE);
USHORT vendorId = 0;
- rc = aUSBDevice->COMGETTER(VendorId) (&vendorId);
+ rc = aUSBDevice->COMGETTER(VendorId)(&vendorId);
ComAssertComRCRet(rc, false);
ComAssertRet(vendorId, false);
- int vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_VENDOR_ID, vendorId, true); AssertRC(vrc);
+ int vrc = USBFilterSetNumExact(&dev, USBFILTERIDX_VENDOR_ID, vendorId, true); AssertRC(vrc);
USHORT productId = 0;
- rc = aUSBDevice->COMGETTER(ProductId) (&productId);
+ rc = aUSBDevice->COMGETTER(ProductId)(&productId);
ComAssertComRCRet(rc, false);
- vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_PRODUCT_ID, productId, true); AssertRC(vrc);
+ vrc = USBFilterSetNumExact(&dev, USBFILTERIDX_PRODUCT_ID, productId, true); AssertRC(vrc);
USHORT revision;
- rc = aUSBDevice->COMGETTER(Revision) (&revision);
+ rc = aUSBDevice->COMGETTER(Revision)(&revision);
ComAssertComRCRet(rc, false);
- vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_DEVICE, revision, true); AssertRC(vrc);
+ vrc = USBFilterSetNumExact(&dev, USBFILTERIDX_DEVICE, revision, true); AssertRC(vrc);
Bstr manufacturer;
- rc = aUSBDevice->COMGETTER(Manufacturer) (manufacturer.asOutParam());
+ rc = aUSBDevice->COMGETTER(Manufacturer)(manufacturer.asOutParam());
ComAssertComRCRet(rc, false);
if (!manufacturer.isEmpty())
- USBFilterSetStringExact (&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer).c_str(), true);
+ USBFilterSetStringExact(&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer).c_str(), true);
Bstr product;
- rc = aUSBDevice->COMGETTER(Product) (product.asOutParam());
+ rc = aUSBDevice->COMGETTER(Product)(product.asOutParam());
ComAssertComRCRet(rc, false);
if (!product.isEmpty())
- USBFilterSetStringExact (&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product).c_str(), true);
+ USBFilterSetStringExact(&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product).c_str(), true);
Bstr serialNumber;
- rc = aUSBDevice->COMGETTER(SerialNumber) (serialNumber.asOutParam());
+ rc = aUSBDevice->COMGETTER(SerialNumber)(serialNumber.asOutParam());
ComAssertComRCRet(rc, false);
if (!serialNumber.isEmpty())
- USBFilterSetStringExact (&dev, USBFILTERIDX_SERIAL_NUMBER_STR, Utf8Str(serialNumber).c_str(), true);
+ USBFilterSetStringExact(&dev, USBFILTERIDX_SERIAL_NUMBER_STR, Utf8Str(serialNumber).c_str(), true);
Bstr address;
- rc = aUSBDevice->COMGETTER(Address) (address.asOutParam());
+ rc = aUSBDevice->COMGETTER(Address)(address.asOutParam());
ComAssertComRCRet(rc, false);
USHORT port = 0;
rc = aUSBDevice->COMGETTER(Port)(&port);
ComAssertComRCRet(rc, false);
- USBFilterSetNumExact (&dev, USBFILTERIDX_PORT, port, true);
+ USBFilterSetNumExact(&dev, USBFILTERIDX_PORT, port, true);
BOOL remote = FALSE;
rc = aUSBDevice->COMGETTER(Remote)(&remote);
@@ -1170,16 +1169,16 @@ bool USBController::hasMatchingFilter (IUSBDevice *aUSBDevice, ULONG *aMaskedIfs
/* apply self filters */
for (DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
it != m->llDeviceFilters->end();
- ++ it)
+ ++it)
{
AutoWriteLock filterLock(*it COMMA_LOCKVAL_SRC_POS);
const USBDeviceFilter::Data &aData = (*it)->getData();
if (!aData.mActive)
continue;
- if (!aData.mRemote.isMatch (remote))
+ if (!aData.mRemote.isMatch(remote))
continue;
- if (!USBFilterMatch (&aData.mUSBFilter, &dev))
+ if (!USBFilterMatch(&aData.mUSBFilter, &dev))
continue;
match = true;
@@ -1201,12 +1200,12 @@ bool USBController::hasMatchingFilter (IUSBDevice *aUSBDevice, ULONG *aMaskedIfs
*
* @note Locks this object for reading.
*/
-HRESULT USBController::notifyProxy (bool aInsertFilters)
+HRESULT USBController::notifyProxy(bool aInsertFilters)
{
LogFlowThisFunc(("aInsertFilters=%RTbool\n", aInsertFilters));
AutoCaller autoCaller(this);
- AssertComRCReturn (autoCaller.rc(), false);
+ AssertComRCReturn(autoCaller.rc(), false);
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -1219,9 +1218,9 @@ HRESULT USBController::notifyProxy (bool aInsertFilters)
USBDeviceFilter *flt = *it; /* resolve ambiguity (for ComPtr below) */
/* notify the proxy (only if the filter is active) */
- if (flt->getData().mActive
- && flt->getData().mRemote.isMatch (false) /* and if the filter is NOT remote */
- )
+ if ( flt->getData().mActive
+ && flt->getData().mRemote.isMatch(false) /* and if the filter is NOT remote */
+ )
{
if (aInsertFilters)
{
@@ -1240,7 +1239,7 @@ HRESULT USBController::notifyProxy (bool aInsertFilters)
}
}
}
- ++ it;
+ ++it;
}
return S_OK;
diff --git a/src/VBox/Main/src-server/USBProxyService.cpp b/src/VBox/Main/src-server/USBProxyService.cpp
index b0ee34435..ddc21035f 100644
--- a/src/VBox/Main/src-server/USBProxyService.cpp
+++ b/src/VBox/Main/src-server/USBProxyService.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -139,7 +139,7 @@ HRESULT USBProxyService::getDeviceCollection(ComSafeArrayOut(IHostUSBDevice *, a
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- SafeIfaceArray<IHostUSBDevice> Collection (mDevices);
+ SafeIfaceArray<IHostUSBDevice> Collection(mDevices);
Collection.detachTo(ComSafeArrayOutArg(aUSBDevices));
return S_OK;
@@ -180,7 +180,7 @@ HRESULT USBProxyService::captureDeviceForVM(SessionMachine *aMachine, IN_GUID aI
/*
* Try to capture the device
*/
- AutoWriteLock DevLock(pHostDevice COMMA_LOCKVAL_SRC_POS);
+ alock.release();
return pHostDevice->requestCaptureForVM(aMachine, true /* aSetError */);
}
@@ -223,7 +223,7 @@ HRESULT USBProxyService::detachDeviceFromVM(SessionMachine *aMachine, IN_GUID aI
ComObjPtr<HostUSBDevice> pHostDevice = findDeviceById(aId);
ComAssertRet(!pHostDevice.isNull(), E_FAIL);
- AutoWriteLock DevLock(pHostDevice COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock devLock(pHostDevice COMMA_LOCKVAL_SRC_POS);
/*
* Work the state machine.
@@ -240,6 +240,8 @@ HRESULT USBProxyService::detachDeviceFromVM(SessionMachine *aMachine, IN_GUID aI
&& fRunFilters)
{
Assert(aDone && pHostDevice->getUnistate() == kHostUSBDeviceState_HeldByProxy && pHostDevice->getMachine().isNull());
+ devLock.release();
+ alock.release();
HRESULT hrc2 = runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine);
ComAssertComRC(hrc2);
}
@@ -264,34 +266,36 @@ HRESULT USBProxyService::detachDeviceFromVM(SessionMachine *aMachine, IN_GUID aI
*
* @returns COM status code, perhaps with error info.
*
- * @remarks Write locks the host object and may temporarily abandon
- * its locks to perform IPC.
+ * @remarks Temporarily locks this object, the machine object and some USB
+ * device, and the called methods will lock similar objects.
*/
HRESULT USBProxyService::autoCaptureDevicesForVM(SessionMachine *aMachine)
{
LogFlowThisFunc(("aMachine=%p{%s}\n",
aMachine,
aMachine->getName().c_str()));
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- AutoWriteLock mlock(aMachine COMMA_LOCKVAL_SRC_POS);
/*
- * Make a copy of the list because we might have to exit and
- * re-enter the lock protecting it. (This will not make copies
- * of any HostUSBDevice objects, only reference them.)
+ * Make a copy of the list because we cannot hold the lock protecting it.
+ * (This will not make copies of any HostUSBDevice objects, only reference them.)
*/
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
HostUSBDeviceList ListCopy = mDevices;
+ alock.release();
for (HostUSBDeviceList::iterator it = ListCopy.begin();
it != ListCopy.end();
++it)
{
ComObjPtr<HostUSBDevice> device = *it;
- AutoWriteLock devLock(device COMMA_LOCKVAL_SRC_POS);
+ AutoReadLock devLock(device COMMA_LOCKVAL_SRC_POS);
if ( device->getUnistate() == kHostUSBDeviceState_HeldByProxy
|| device->getUnistate() == kHostUSBDeviceState_Unused
|| device->getUnistate() == kHostUSBDeviceState_Capturable)
+ {
+ devLock.release();
runMachineFilters(aMachine, device);
+ }
}
return S_OK;
@@ -322,7 +326,7 @@ HRESULT USBProxyService::autoCaptureDevicesForVM(SessionMachine *aMachine)
HRESULT USBProxyService::detachAllDevicesFromVM(SessionMachine *aMachine, bool aDone, bool aAbnormal)
{
// get a list of all running machines while we're outside the lock
- // (getOpenedMachines requests locks which are incompatible with the lock of the machines list)
+ // (getOpenedMachines requests locks which are incompatible with the host object lock)
SessionMachinesList llOpenedMachines;
mHost->parent()->getOpenedMachines(llOpenedMachines);
@@ -335,11 +339,11 @@ HRESULT USBProxyService::detachAllDevicesFromVM(SessionMachine *aMachine, bool a
*/
HostUSBDeviceList ListCopy = mDevices;
- for (HostUSBDeviceList::iterator It = ListCopy.begin();
- It != ListCopy.end();
- ++It)
+ for (HostUSBDeviceList::iterator it = ListCopy.begin();
+ it != ListCopy.end();
+ ++it)
{
- ComObjPtr<HostUSBDevice> pHostDevice = *It;
+ ComObjPtr<HostUSBDevice> pHostDevice = *it;
AutoWriteLock devLock(pHostDevice COMMA_LOCKVAL_SRC_POS);
if (pHostDevice->getMachine() == aMachine)
{
@@ -352,8 +356,11 @@ HRESULT USBProxyService::detachAllDevicesFromVM(SessionMachine *aMachine, bool a
&& fRunFilters)
{
Assert(aDone && pHostDevice->getUnistate() == kHostUSBDeviceState_HeldByProxy && pHostDevice->getMachine().isNull());
+ devLock.release();
+ alock.release();
HRESULT hrc2 = runAllFiltersOnDevice(pHostDevice, llOpenedMachines, aMachine);
ComAssertComRC(hrc2);
+ alock.acquire();
}
}
}
@@ -381,8 +388,7 @@ HRESULT USBProxyService::detachAllDevicesFromVM(SessionMachine *aMachine, bool a
* @param aIgnoreMachine The machine to ignore filters from (we've just
* detached the device from this machine).
*
- * @note The caller is expected to own both the device and Host write locks,
- * and be prepared that these locks may be abandond temporarily.
+ * @note The caller is expected to own no locks.
*/
HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice,
SessionMachinesList &llOpenedMachines,
@@ -393,8 +399,10 @@ HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice
/*
* Verify preconditions.
*/
- AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), E_FAIL);
+ AssertReturn(!isWriteLockOnCurrentThread(), E_FAIL);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), E_FAIL);
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ AutoWriteLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
AssertMsgReturn(aDevice->isCapturableOrHeld(), ("{%s} %s\n", aDevice->getName().c_str(), aDevice->getStateName()), E_FAIL);
/*
@@ -405,7 +413,7 @@ HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice
mHost->getUSBFilters(&globalFilters);
/*
- * Run global filters filerts first.
+ * Run global filters filters first.
*/
bool fHoldIt = false;
for (Host::USBDeviceFilterList::const_iterator it = globalFilters.begin();
@@ -423,6 +431,9 @@ HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice
/*
* Release the device to the host and we're done.
*/
+ filterLock.release();
+ devLock.release();
+ alock.release();
aDevice->requestReleaseToHost();
return S_OK;
}
@@ -455,17 +466,23 @@ HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice
continue;
/* runMachineFilters takes care of checking the machine state. */
+ devLock.release();
+ alock.release();
if (runMachineFilters(pMachine, aDevice))
{
LogFlowThisFunc(("{%s} attached to %p\n", aDevice->getName().c_str(), (void *)pMachine));
return S_OK;
}
+ alock.acquire();
+ devLock.acquire();
}
/*
* No matching machine, so request hold or release depending
* on global filter match.
*/
+ devLock.release();
+ alock.release();
if (fHoldIt)
aDevice->requestHold();
else
@@ -484,8 +501,7 @@ HRESULT USBProxyService::runAllFiltersOnDevice(ComObjPtr<HostUSBDevice> &aDevice
* @param aDevice The USB device in question.
* @returns @c true if the device has been or is being attached to the VM, @c false otherwise.
*
- * @note Caller must own the USB and device locks for writing.
- * @note Locks aMachine for reading.
+ * @note Locks several objects temporarily for reading or writing.
*/
bool USBProxyService::runMachineFilters(SessionMachine *aMachine, ComObjPtr<HostUSBDevice> &aDevice)
{
@@ -495,8 +511,9 @@ bool USBProxyService::runMachineFilters(SessionMachine *aMachine, ComObjPtr<Host
* Validate preconditions.
*/
AssertReturn(aMachine, false);
- AssertReturn(isWriteLockOnCurrentThread(), false);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), false);
+ AssertReturn(!isWriteLockOnCurrentThread(), false);
+ AssertReturn(!aMachine->isWriteLockOnCurrentThread(), false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
/* Let HostUSBDevice::requestCaptureToVM() validate the state. */
/*
@@ -573,6 +590,8 @@ void USBProxyService::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSucce
* The device is going to be detached from a VM.
*
* @param aDevice The device in question.
+ *
+ * @todo unused
*/
void USBProxyService::detachingDevice(HostUSBDevice *aDevice)
{
@@ -819,6 +838,7 @@ static PUSBDEVICE sortDevices(PUSBDEVICE pDevices)
}
}
+ LogFlowFuncLeave();
return pHead;
}
@@ -839,24 +859,24 @@ void USBProxyService::processChanges(void)
pDevices = sortDevices(pDevices);
// get a list of all running machines while we're outside the lock
- // (getOpenedMachines requests locks which are incompatible with the lock of the machines list)
+ // (getOpenedMachines requests higher priority locks)
SessionMachinesList llOpenedMachines;
mHost->parent()->getOpenedMachines(llOpenedMachines);
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
/*
- * Compare previous list with the previous list of devices
+ * Compare previous list with the new list of devices
* and merge in any changes while notifying Host.
*/
- HostUSBDeviceList::iterator It = this->mDevices.begin();
- while ( It != mDevices.end()
+ HostUSBDeviceList::iterator it = this->mDevices.begin();
+ while ( it != mDevices.end()
|| pDevices)
{
ComObjPtr<HostUSBDevice> pHostDevice;
- if (It != mDevices.end())
- pHostDevice = *It;
+ if (it != mDevices.end())
+ pHostDevice = *it;
/*
* Assert that the object is still alive (we still reference it in
@@ -897,11 +917,14 @@ void USBProxyService::processChanges(void)
bool fRunFilters = false;
SessionMachine *pIgnoreMachine = NULL;
+ devLock.release();
+ alock.release();
if (updateDeviceState(pHostDevice, pCur, &fRunFilters, &pIgnoreMachine))
deviceChanged(pHostDevice,
(fRunFilters ? &llOpenedMachines : NULL),
pIgnoreMachine);
- It++;
+ alock.acquire();
+ it++;
}
else
{
@@ -927,11 +950,12 @@ void USBProxyService::processChanges(void)
pNew->pszProduct,
pNew->pszManufacturer));
- mDevices.insert(It, NewObj);
+ mDevices.insert(it, NewObj);
- /* Not really necessary to lock here, but make Assert checks happy. */
- AutoWriteLock newDevLock(NewObj COMMA_LOCKVAL_SRC_POS);
+ devLock.release();
+ alock.release();
deviceAdded(NewObj, llOpenedMachines, pNew);
+ alock.acquire();
}
else
{
@@ -940,10 +964,12 @@ void USBProxyService::processChanges(void)
* as the result of a re-enumeration.
*/
if (!pHostDevice->wasActuallyDetached())
- It++;
+ it++;
else
{
- It = mDevices.erase(It);
+ it = mDevices.erase(it);
+ devLock.release();
+ alock.release();
deviceRemoved(pHostDevice);
Log(("USBProxyService::processChanges: detached %p {%s}\n",
(HostUSBDevice *)pHostDevice,
@@ -953,6 +979,7 @@ void USBProxyService::processChanges(void)
* uninitialize to avoid abuse */
devCaller.release();
pHostDevice->uninit();
+ alock.acquire();
}
}
}
@@ -992,8 +1019,9 @@ void USBProxyService::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice,
/*
* Validate preconditions.
*/
- AssertReturnVoid(isWriteLockOnCurrentThread());
- AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
+ AssertReturnVoid(!isWriteLockOnCurrentThread());
+ AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid}\n",
(HostUSBDevice *)aDevice,
aDevice->getName().c_str(),
@@ -1005,6 +1033,7 @@ void USBProxyService::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice,
*/
if (aDevice->isCapturableOrHeld())
{
+ devLock.release();
HRESULT rc = runAllFiltersOnDevice(aDevice, llOpenedMachines, NULL /* aIgnoreMachine */);
AssertComRC(rc);
}
@@ -1025,8 +1054,9 @@ void USBProxyService::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice)
/*
* Validate preconditions.
*/
- AssertReturnVoid(isWriteLockOnCurrentThread());
- AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
+ AssertReturnVoid(!isWriteLockOnCurrentThread());
+ AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
+ AutoWriteLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid}\n",
(HostUSBDevice *)aDevice,
aDevice->getName().c_str(),
@@ -1037,6 +1067,7 @@ void USBProxyService::deviceRemoved(ComObjPtr<HostUSBDevice> &aDevice)
* Detach the device from any machine currently using it,
* reset all data and uninitialize the device object.
*/
+ devLock.release();
aDevice->onPhysicalDetached();
}
@@ -1054,7 +1085,7 @@ bool USBProxyService::updateDeviceStateFake(HostUSBDevice *aDevice, PUSBDEVICE a
*aRunFilters = false;
*aIgnoreMachine = NULL;
AssertReturn(aDevice, false);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
/*
* Just hand it to the device, it knows best what needs to be done.
@@ -1077,7 +1108,7 @@ bool USBProxyService::updateDeviceStateFake(HostUSBDevice *aDevice, PUSBDEVICE a
bool USBProxyService::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
AssertReturn(aDevice, false);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
return aDevice->updateState(aUSBDevice, aRunFilters, aIgnoreMachine);
}
@@ -1098,8 +1129,9 @@ void USBProxyService::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMa
/*
* Validate preconditions.
*/
- AssertReturnVoid(isWriteLockOnCurrentThread());
- AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
+ AssertReturnVoid(!isWriteLockOnCurrentThread());
+ AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("aDevice=%p name={%s} state=%s id={%RTuuid} aRunFilters=%RTbool aIgnoreMachine=%p\n",
(HostUSBDevice *)aDevice,
aDevice->getName().c_str(),
@@ -1107,6 +1139,7 @@ void USBProxyService::deviceChanged(ComObjPtr<HostUSBDevice> &aDevice, SessionMa
aDevice->getId().raw(),
(pllOpenedMachines != NULL), // used to be "bool aRunFilters"
aIgnoreMachine));
+ devLock.release();
/*
* Run filters if requested to do so.
@@ -1211,12 +1244,12 @@ ComObjPtr<HostUSBDevice> USBProxyService::findDeviceById(IN_GUID aId)
{
Guid Id(aId);
ComObjPtr<HostUSBDevice> Dev;
- for (HostUSBDeviceList::iterator It = mDevices.begin();
- It != mDevices.end();
- ++It)
- if ((*It)->getId() == Id)
+ for (HostUSBDeviceList::iterator it = mDevices.begin();
+ it != mDevices.end();
+ ++it)
+ if ((*it)->getId() == Id)
{
- Dev = (*It);
+ Dev = (*it);
break;
}
diff --git a/src/VBox/Main/src-server/VirtualBoxImpl.cpp b/src/VBox/Main/src-server/VirtualBoxImpl.cpp
index a84300812..d90b0b0b2 100644
--- a/src/VBox/Main/src-server/VirtualBoxImpl.cpp
+++ b/src/VBox/Main/src-server/VirtualBoxImpl.cpp
@@ -1,5 +1,4 @@
/* $Id: VirtualBoxImpl.cpp $ */
-
/** @file
* Implementation of IVirtualBox in VBoxSVC.
*/
@@ -17,6 +16,7 @@
*/
#include <iprt/asm.h>
+#include <iprt/base64.h>
#include <iprt/buildconfig.h>
#include <iprt/cpp/utils.h>
#include <iprt/dir.h>
@@ -24,7 +24,10 @@
#include <iprt/file.h>
#include <iprt/path.h>
#include <iprt/process.h>
+#include <iprt/rand.h>
+#include <iprt/sha.h>
#include <iprt/string.h>
+#include <iprt/stream.h>
#include <iprt/thread.h>
#include <iprt/uuid.h>
#include <iprt/cpp/xml.h>
@@ -45,8 +48,6 @@
#include <vector>
#include <memory> // for auto_ptr
-#include <typeinfo>
-
#include "VirtualBoxImpl.h"
#include "Global.h"
@@ -69,6 +70,7 @@
#ifdef VBOX_WITH_EXTPACK
# include "ExtPackManagerImpl.h"
#endif
+#include "AutostartDb.h"
#include "AutoCaller.h"
#include "Logging.h"
@@ -97,6 +99,9 @@
Bstr VirtualBox::sVersion;
// static
+Bstr VirtualBox::sVersionNormalized;
+
+// static
ULONG VirtualBox::sRevision;
// static
@@ -105,6 +110,12 @@ Bstr VirtualBox::sPackageType;
// static
Bstr VirtualBox::sAPIVersion;
+#ifdef VBOX_WITH_SYS_V_IPC_SESSION_WATCHER
+/** Table for adaptive timeouts in the client watcher. The counter starts at
+ * the maximum value and decreases to 0. */
+static const RTMSINTERVAL s_updateAdaptTimeouts[] = { 500, 200, 100, 50, 20, 10, 5 };
+#endif
+
////////////////////////////////////////////////////////////////////////////////
//
// CallbackEvent class
@@ -184,6 +195,7 @@ struct VirtualBox::Data
Data()
: pMainConfigFile(NULL),
uuidMediaRegistry("48024e5c-fdd9-470f-93af-ec29f7ea518c"),
+ uRegistryNeedsSaving(0),
lockMachines(LOCKCLASS_LISTOFMACHINES),
allMachines(lockMachines),
lockGuestOSTypes(LOCKCLASS_LISTOFOTHEROBJECTS),
@@ -200,7 +212,9 @@ struct VirtualBox::Data
updateReq(UPDATEREQARG),
threadClientWatcher(NIL_RTTHREAD),
threadAsyncEvent(NIL_RTTHREAD),
- pAsyncEventQ(NULL)
+ pAsyncEventQ(NULL),
+ pAutostartDb(NULL),
+ fSettingsCipherKeySet(false)
{
}
@@ -223,6 +237,10 @@ struct VirtualBox::Data
// constant pseudo-machine ID for global media registry
const Guid uuidMediaRegistry;
+ // counter if global media registry needs saving, updated using atomic
+ // operations, without requiring any locks
+ uint64_t uRegistryNeedsSaving;
+
// const objects not requiring locking
const ComObjPtr<Host> pHost;
const ComObjPtr<SystemProperties> pSystemProperties;
@@ -273,6 +291,9 @@ struct VirtualBox::Data
// the following are data for the client watcher thread
const UPDATEREQTYPE updateReq;
+#ifdef VBOX_WITH_SYS_V_IPC_SESSION_WATCHER
+ uint8_t updateAdaptCtr;
+#endif
const RTTHREAD threadClientWatcher;
typedef std::list<RTPROCESS> ProcessList;
ProcessList llProcesses;
@@ -286,8 +307,16 @@ struct VirtualBox::Data
/** The extension pack manager object lives here. */
const ComObjPtr<ExtPackManager> ptrExtPackManager;
#endif
+
+ /** The global autostart database for the user. */
+ AutostartDb * const pAutostartDb;
+
+ /** Settings secret */
+ bool fSettingsCipherKeySet;
+ uint8_t SettingsCipherKey[RTSHA512_HASH_SIZE];
};
+
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
@@ -343,7 +372,14 @@ HRESULT VirtualBox::init()
LogFlowThisFuncEnter();
if (sVersion.isEmpty())
- sVersion = VBOX_VERSION_STRING;
+ sVersion = RTBldCfgVersion();
+ if (sVersionNormalized.isEmpty())
+ {
+ Utf8Str tmp(RTBldCfgVersion());
+ if (tmp.endsWith(VBOX_BUILD_PUBLISHER))
+ tmp = tmp.substr(0, tmp.length() - strlen(VBOX_BUILD_PUBLISHER));
+ sVersionNormalized = tmp;
+ }
sRevision = RTBldCfgRevision();
if (sPackageType.isEmpty())
sPackageType = VBOX_PACKAGE_STRING;
@@ -406,6 +442,12 @@ HRESULT VirtualBox::init()
rc = m->pHost->loadSettings(m->pMainConfigFile->host);
if (FAILED(rc)) throw rc;
+ /*
+ * Create autostart database object early, because the system properties
+ * might need it.
+ */
+ unconst(m->pAutostartDb) = new AutostartDb;
+
/* create the system properties object, someone may need it too */
unconst(m->pSystemProperties).createObject();
rc = m->pSystemProperties->init(this);
@@ -415,7 +457,7 @@ HRESULT VirtualBox::init()
if (FAILED(rc)) throw rc;
/* guest OS type objects, needed by machines */
- for (size_t i = 0; i < RT_ELEMENTS(Global::sOSTypes); ++i)
+ for (size_t i = 0; i < Global::cOSTypes; ++i)
{
ComObjPtr<GuestOSType> guestOSTypeObj;
rc = guestOSTypeObj.createObject();
@@ -438,7 +480,6 @@ HRESULT VirtualBox::init()
if (FAILED(rc = initMachines()))
throw rc;
-
#ifdef DEBUG
LogFlowThisFunc(("Dumping media backreferences\n"));
dumpAllBackRefs();
@@ -481,7 +522,7 @@ HRESULT VirtualBox::init()
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
if (SUCCEEDED(rc))
@@ -493,6 +534,7 @@ HRESULT VirtualBox::init()
RTSemEventCreate(&unconst(m->updateReq));
#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
RTSemEventCreate(&unconst(m->updateReq));
+ ASMAtomicUoWriteU8(&m->updateAdaptCtr, 0);
#else
# error "Port me!"
#endif
@@ -564,9 +606,9 @@ HRESULT VirtualBox::initMachines()
ComObjPtr<Machine> pMachine;
if (SUCCEEDED(rc = pMachine.createObject()))
{
- rc = pMachine->init(this,
- xmlMachine.strSettingsFile,
- &uuid);
+ rc = pMachine->initFromSettings(this,
+ xmlMachine.strSettingsFile,
+ &uuid);
if (SUCCEEDED(rc))
rc = registerMachine(pMachine);
if (FAILED(rc))
@@ -627,7 +669,7 @@ HRESULT VirtualBox::initMedia(const Guid &uuidRegistry,
strMachineFolder);
if (FAILED(rc)) return rc;
- rc = registerMedium(pHardDisk, &pHardDisk, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */);
+ rc = registerMedium(pHardDisk, &pHardDisk, DeviceType_HardDisk);
if (FAILED(rc)) return rc;
}
@@ -647,9 +689,7 @@ HRESULT VirtualBox::initMedia(const Guid &uuidRegistry,
strMachineFolder);
if (FAILED(rc)) return rc;
- rc = registerMedium(pImage, &pImage,
- DeviceType_DVD,
- NULL /* pllRegistriesThatNeedSaving */);
+ rc = registerMedium(pImage, &pImage, DeviceType_DVD);
if (FAILED(rc)) return rc;
}
@@ -669,9 +709,7 @@ HRESULT VirtualBox::initMedia(const Guid &uuidRegistry,
strMachineFolder);
if (FAILED(rc)) return rc;
- rc = registerMedium(pImage, &pImage,
- DeviceType_Floppy,
- NULL /* pllRegistriesThatNeedSaving */);
+ rc = registerMedium(pImage, &pImage, DeviceType_Floppy);
if (FAILED(rc)) return rc;
}
@@ -682,6 +720,10 @@ HRESULT VirtualBox::initMedia(const Guid &uuidRegistry,
void VirtualBox::uninit()
{
+ Assert(!m->uRegistryNeedsSaving);
+ if (m->uRegistryNeedsSaving)
+ saveSettings();
+
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan(this);
if (autoUninitSpan.uninitDone())
@@ -801,6 +843,8 @@ void VirtualBox::uninit()
# error "Port me!"
#endif
+ delete m->pAutostartDb;
+
// clean up our instance data
delete m;
@@ -825,6 +869,17 @@ STDMETHODIMP VirtualBox::COMGETTER(Version)(BSTR *aVersion)
return S_OK;
}
+STDMETHODIMP VirtualBox::COMGETTER(VersionNormalized)(BSTR *aVersionNormalized)
+{
+ CheckComArgNotNull(aVersionNormalized);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ sVersionNormalized.cloneTo(aVersionNormalized);
+ return S_OK;
+}
+
STDMETHODIMP VirtualBox::COMGETTER(Revision)(ULONG *aRevision)
{
CheckComArgNotNull(aRevision);
@@ -884,7 +939,7 @@ STDMETHODIMP VirtualBox::COMGETTER(SettingsFilePath)(BSTR *aSettingsFilePath)
STDMETHODIMP VirtualBox::COMGETTER(Host)(IHost **aHost)
{
- CheckComArgOutSafeArrayPointerValid(aHost);
+ CheckComArgOutPointerValid(aHost);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -897,7 +952,7 @@ STDMETHODIMP VirtualBox::COMGETTER(Host)(IHost **aHost)
STDMETHODIMP
VirtualBox::COMGETTER(SystemProperties)(ISystemProperties **aSystemProperties)
{
- CheckComArgOutSafeArrayPointerValid(aSystemProperties);
+ CheckComArgOutPointerValid(aSystemProperties);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -910,8 +965,7 @@ VirtualBox::COMGETTER(SystemProperties)(ISystemProperties **aSystemProperties)
STDMETHODIMP
VirtualBox::COMGETTER(Machines)(ComSafeArrayOut(IMachine *, aMachines))
{
- if (ComSafeArrayOutIsNull(aMachines))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aMachines);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -923,10 +977,62 @@ VirtualBox::COMGETTER(Machines)(ComSafeArrayOut(IMachine *, aMachines))
return S_OK;
}
+STDMETHODIMP
+VirtualBox::COMGETTER(MachineGroups)(ComSafeArrayOut(BSTR, aMachineGroups))
+{
+ CheckComArgOutSafeArrayPointerValid(aMachineGroups);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ std::list<Bstr> allGroups;
+
+ /* get copy of all machine references, to avoid holding the list lock */
+ MachinesOList::MyList allMachines;
+ {
+ AutoReadLock al(m->allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
+ allMachines = m->allMachines.getList();
+ }
+ for (MachinesOList::MyList::const_iterator it = allMachines.begin();
+ it != allMachines.end();
+ ++it)
+ {
+ const ComObjPtr<Machine> &pMachine = *it;
+ AutoCaller autoMachineCaller(pMachine);
+ if (FAILED(autoMachineCaller.rc()))
+ continue;
+ AutoReadLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
+
+ if (pMachine->isAccessible())
+ {
+ const StringsList &thisGroups = pMachine->getGroups();
+ for (StringsList::const_iterator it2 = thisGroups.begin();
+ it2 != thisGroups.end();
+ ++it2)
+ allGroups.push_back(*it2);
+ }
+ }
+
+ /* throw out any duplicates */
+ allGroups.sort();
+ allGroups.unique();
+ com::SafeArray<BSTR> machineGroups(allGroups.size());
+ size_t i = 0;
+ for (std::list<Bstr>::const_iterator it = allGroups.begin();
+ it != allGroups.end();
+ ++it, i++)
+ {
+ const Bstr &tmp = *it;
+ tmp.cloneTo(&machineGroups[i]);
+ }
+ machineGroups.detachTo(ComSafeArrayOutArg(aMachineGroups));
+
+ return S_OK;
+}
+
STDMETHODIMP VirtualBox::COMGETTER(HardDisks)(ComSafeArrayOut(IMedium *, aHardDisks))
{
- if (ComSafeArrayOutIsNull(aHardDisks))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aHardDisks);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -940,8 +1046,7 @@ STDMETHODIMP VirtualBox::COMGETTER(HardDisks)(ComSafeArrayOut(IMedium *, aHardDi
STDMETHODIMP VirtualBox::COMGETTER(DVDImages)(ComSafeArrayOut(IMedium *, aDVDImages))
{
- if (ComSafeArrayOutIsNull(aDVDImages))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aDVDImages);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -955,8 +1060,7 @@ STDMETHODIMP VirtualBox::COMGETTER(DVDImages)(ComSafeArrayOut(IMedium *, aDVDIma
STDMETHODIMP VirtualBox::COMGETTER(FloppyImages)(ComSafeArrayOut(IMedium *, aFloppyImages))
{
- if (ComSafeArrayOutIsNull(aFloppyImages))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aFloppyImages);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -970,7 +1074,7 @@ STDMETHODIMP VirtualBox::COMGETTER(FloppyImages)(ComSafeArrayOut(IMedium *, aFlo
STDMETHODIMP VirtualBox::COMGETTER(ProgressOperations)(ComSafeArrayOut(IProgress *, aOperations))
{
- CheckComArgOutSafeArrayPointerValid(aOperations);
+ CheckComArgOutPointerValid(aOperations);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1015,7 +1119,7 @@ STDMETHODIMP
VirtualBox::COMGETTER(PerformanceCollector)(IPerformanceCollector **aPerformanceCollector)
{
#ifdef VBOX_WITH_RESOURCE_USAGE_API
- CheckComArgOutSafeArrayPointerValid(aPerformanceCollector);
+ CheckComArgOutPointerValid(aPerformanceCollector);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1032,8 +1136,7 @@ VirtualBox::COMGETTER(PerformanceCollector)(IPerformanceCollector **aPerformance
STDMETHODIMP
VirtualBox::COMGETTER(DHCPServers)(ComSafeArrayOut(IDHCPServer *, aDHCPServers))
{
- if (ComSafeArrayOutIsNull(aDHCPServers))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aDHCPServers);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1081,8 +1184,7 @@ VirtualBox::COMGETTER(ExtensionPackManager)(IExtPackManager **aExtPackManager)
STDMETHODIMP VirtualBox::COMGETTER(InternalNetworks)(ComSafeArrayOut(BSTR, aInternalNetworks))
{
- if (ComSafeArrayOutIsNull(aInternalNetworks))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aInternalNetworks);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1107,15 +1209,11 @@ STDMETHODIMP VirtualBox::COMGETTER(InternalNetworks)(ComSafeArrayOut(BSTR, aInte
if (pMachine->isAccessible())
{
- ULONG cNetworkAdapters = 0;
- HRESULT rc = m->pSystemProperties->GetMaxNetworkAdapters(pMachine->getChipsetType(), &cNetworkAdapters);
- if (FAILED(rc))
- continue;
- cNetworkAdapters = RT_MIN(4, cNetworkAdapters);
+ uint32_t cNetworkAdapters = Global::getMaxNetworkAdapters(pMachine->getChipsetType());
for (ULONG i = 0; i < cNetworkAdapters; i++)
{
ComPtr<INetworkAdapter> pNet;
- rc = pMachine->GetNetworkAdapter(i, pNet.asOutParam());
+ HRESULT rc = pMachine->GetNetworkAdapter(i, pNet.asOutParam());
if (FAILED(rc) || pNet.isNull())
continue;
Bstr strInternalNetwork;
@@ -1147,8 +1245,7 @@ STDMETHODIMP VirtualBox::COMGETTER(InternalNetworks)(ComSafeArrayOut(BSTR, aInte
STDMETHODIMP VirtualBox::COMGETTER(GenericNetworkDrivers)(ComSafeArrayOut(BSTR, aGenericNetworkDrivers))
{
- if (ComSafeArrayOutIsNull(aGenericNetworkDrivers))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aGenericNetworkDrivers);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1173,15 +1270,11 @@ STDMETHODIMP VirtualBox::COMGETTER(GenericNetworkDrivers)(ComSafeArrayOut(BSTR,
if (pMachine->isAccessible())
{
- ULONG cNetworkAdapters = 0;
- HRESULT rc = m->pSystemProperties->GetMaxNetworkAdapters(pMachine->getChipsetType(), &cNetworkAdapters);
- if (FAILED(rc))
- continue;
- cNetworkAdapters = RT_MIN(4, cNetworkAdapters);
+ uint32_t cNetworkAdapters = Global::getMaxNetworkAdapters(pMachine->getChipsetType());
for (ULONG i = 0; i < cNetworkAdapters; i++)
{
ComPtr<INetworkAdapter> pNet;
- rc = pMachine->GetNetworkAdapter(i, pNet.asOutParam());
+ HRESULT rc = pMachine->GetNetworkAdapter(i, pNet.asOutParam());
if (FAILED(rc) || pNet.isNull())
continue;
Bstr strGenericNetworkDriver;
@@ -1307,7 +1400,12 @@ VirtualBox::CheckFirmwarePresent(FirmwareType_T aFirmwareType,
// IVirtualBox methods
/////////////////////////////////////////////////////////////////////////////
+/* Helper for VirtualBox::ComposeMachineFilename */
+static void sanitiseMachineFilename(Utf8Str &aName);
+
STDMETHODIMP VirtualBox::ComposeMachineFilename(IN_BSTR aName,
+ IN_BSTR aGroup,
+ IN_BSTR aCreateFlags,
IN_BSTR aBaseFolder,
BSTR *aFilename)
{
@@ -1320,42 +1418,185 @@ STDMETHODIMP VirtualBox::ComposeMachineFilename(IN_BSTR aName,
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ Utf8Str strCreateFlags(aCreateFlags);
+ Guid id;
+ bool fDirectoryIncludesUUID = false;
+ if (!strCreateFlags.isEmpty())
+ {
+ const char *pcszNext = strCreateFlags.c_str();
+ while (*pcszNext != '\0')
+ {
+ Utf8Str strFlag;
+ const char *pcszComma = RTStrStr(pcszNext, ",");
+ if (!pcszComma)
+ strFlag = pcszNext;
+ else
+ strFlag = Utf8Str(pcszNext, pcszComma - pcszNext);
+
+ const char *pcszEqual = RTStrStr(strFlag.c_str(), "=");
+ /* skip over everything which doesn't contain '=' */
+ if (pcszEqual && pcszEqual != strFlag.c_str())
+ {
+ Utf8Str strKey(strFlag.c_str(), pcszEqual - strFlag.c_str());
+ Utf8Str strValue(strFlag.c_str() + (pcszEqual - strFlag.c_str() + 1));
+
+ if (strKey == "UUID")
+ id = strValue.c_str();
+ else if (strKey == "directoryIncludesUUID")
+ fDirectoryIncludesUUID = (strValue == "1");
+ }
+
+ if (!pcszComma)
+ pcszNext += strFlag.length();
+ else
+ pcszNext += strFlag.length() + 1;
+ }
+ }
+ if (id.isEmpty())
+ fDirectoryIncludesUUID = false;
+
+ Utf8Str strGroup(aGroup);
+ if (strGroup.isEmpty())
+ strGroup = "/";
+ HRESULT rc = validateMachineGroup(strGroup, true);
+ if (FAILED(rc))
+ return rc;
+
/* Compose the settings file name using the following scheme:
*
- * <base_folder>/<machine_name>/<machine_name>.xml
+ * <base_folder><group>/<machine_name>/<machine_name>.xml
*
* If a non-null and non-empty base folder is specified, the default
* machine folder will be used as a base folder.
+ * We sanitise the machine name to a safe white list of characters before
+ * using it.
*/
Utf8Str strBase = aBaseFolder;
+ Utf8Str strName = aName;
+ Utf8Str strDirName(strName);
+ if (fDirectoryIncludesUUID)
+ strDirName += Utf8StrFmt(" (%RTuuid)", id.raw());
+ sanitiseMachineFilename(strName);
+ sanitiseMachineFilename(strDirName);
+
if (strBase.isEmpty())
/* we use the non-full folder value below to keep the path relative */
getDefaultMachineFolder(strBase);
calculateFullPath(strBase, strBase);
- Bstr bstrSettingsFile = BstrFmt("%s%c%ls%c%ls.vbox",
+ /* eliminate toplevel group to avoid // in the result */
+ if (strGroup == "/")
+ strGroup.setNull();
+ Bstr bstrSettingsFile = BstrFmt("%s%s%c%s%c%s.vbox",
strBase.c_str(),
+ strGroup.c_str(),
RTPATH_DELIMITER,
- aName,
+ strDirName.c_str(),
RTPATH_DELIMITER,
- aName);
+ strName.c_str());
bstrSettingsFile.detachTo(aFilename);
return S_OK;
}
+/**
+ * Remove characters from a machine file name which can be problematic on
+ * particular systems.
+ * @param strName The file name to sanitise.
+ */
+void sanitiseMachineFilename(Utf8Str &strName)
+{
+ /** Set of characters which should be safe for use in filenames: some basic
+ * ASCII, Unicode from Latin-1 alphabetic to the end of Hangul. We try to
+ * skip anything that could count as a control character in Windows or
+ * *nix, or be otherwise difficult for shells to handle (I would have
+ * preferred to remove the space and brackets too). We also remove all
+ * characters which need UTF-16 surrogate pairs for Windows's benefit. */
+#ifdef RT_STRICT
+ RTUNICP aCpSet[] =
+ { ' ', ' ', '(', ')', '-', '.', '0', '9', 'A', 'Z', 'a', 'z', '_', '_',
+ 0xa0, 0xd7af, '\0' };
+#endif
+ char *pszName = strName.mutableRaw();
+ Assert(RTStrPurgeComplementSet(pszName, aCpSet, '_') >= 0);
+ /* No leading dot or dash. */
+ if (pszName[0] == '.' || pszName[0] == '-')
+ pszName[0] = '_';
+ /* No trailing dot. */
+ if (pszName[strName.length() - 1] == '.')
+ pszName[strName.length() - 1] = '_';
+ /* Mangle leading and trailing spaces. */
+ for (size_t i = 0; pszName[i] == ' '; ++i)
+ pszName[i] = '_';
+ for (size_t i = strName.length() - 1; i && pszName[i] == ' '; --i)
+ pszName[i] = '_';
+}
+
+#ifdef DEBUG
+/** Simple unit test/operation examples for sanitiseMachineFilename(). */
+static unsigned testSanitiseMachineFilename(void (*pfnPrintf)(const char *, ...))
+{
+ unsigned cErrors = 0;
+
+ /** Expected results of sanitising given file names. */
+ static struct
+ {
+ /** The test file name to be sanitised (Utf-8). */
+ const char *pcszIn;
+ /** The expected sanitised output (Utf-8). */
+ const char *pcszOutExpected;
+ } aTest[] =
+ {
+ { "OS/2 2.1", "OS_2 2.1" },
+ { "-!My VM!-", "__My VM_-" },
+ { "\xF0\x90\x8C\xB0", "____" },
+ { " My VM ", "__My VM__" },
+ { ".My VM.", "_My VM_" },
+ { "My VM", "My VM" }
+ };
+ for (unsigned i = 0; i < RT_ELEMENTS(aTest); ++i)
+ {
+ Utf8Str str(aTest[i].pcszIn);
+ sanitiseMachineFilename(str);
+ if (str.compare(aTest[i].pcszOutExpected))
+ {
+ ++cErrors;
+ pfnPrintf("%s: line %d, expected %s, actual %s\n",
+ __PRETTY_FUNCTION__, i, aTest[i].pcszOutExpected,
+ str.c_str());
+ }
+ }
+ return cErrors;
+}
+
+/** @todo Proper testcase. */
+/** @todo Do we have a better method of doing init functions? */
+namespace
+{
+ class TestSanitiseMachineFilename
+ {
+ public:
+ TestSanitiseMachineFilename(void)
+ {
+ Assert(!testSanitiseMachineFilename(RTAssertMsg2));
+ }
+ };
+ TestSanitiseMachineFilename s_TestSanitiseMachineFilename;
+}
+#endif
+
/** @note Locks mSystemProperties object for reading. */
STDMETHODIMP VirtualBox::CreateMachine(IN_BSTR aSettingsFile,
IN_BSTR aName,
+ ComSafeArrayIn(IN_BSTR, aGroups),
IN_BSTR aOsTypeId,
- IN_BSTR aId,
- BOOL forceOverwrite,
+ IN_BSTR aCreateFlags,
IMachine **aMachine)
{
LogFlowThisFuncEnter();
- LogFlowThisFunc(("aSettingsFile=\"%ls\", aName=\"%ls\", aOsTypeId =\"%ls\"\n", aSettingsFile, aName, aOsTypeId));
+ LogFlowThisFunc(("aSettingsFile=\"%ls\", aName=\"%ls\", aOsTypeId =\"%ls\", aCreateFlags=\"%ls\"\n", aSettingsFile, aName, aOsTypeId, aCreateFlags));
CheckComArgStrNotEmptyOrNull(aName);
/** @todo tighten checks on aId? */
@@ -1364,13 +1605,64 @@ STDMETHODIMP VirtualBox::CreateMachine(IN_BSTR aSettingsFile,
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ StringsList llGroups;
+ HRESULT rc = convertMachineGroups(ComSafeArrayInArg(aGroups), &llGroups);
+ if (FAILED(rc))
+ return rc;
+
+ Utf8Str strCreateFlags(aCreateFlags);
+ Guid id;
+ bool fForceOverwrite = false;
+ bool fDirectoryIncludesUUID = false;
+ if (!strCreateFlags.isEmpty())
+ {
+ const char *pcszNext = strCreateFlags.c_str();
+ while (*pcszNext != '\0')
+ {
+ Utf8Str strFlag;
+ const char *pcszComma = RTStrStr(pcszNext, ",");
+ if (!pcszComma)
+ strFlag = pcszNext;
+ else
+ strFlag = Utf8Str(pcszNext, pcszComma - pcszNext);
+
+ const char *pcszEqual = RTStrStr(strFlag.c_str(), "=");
+ /* skip over everything which doesn't contain '=' */
+ if (pcszEqual && pcszEqual != strFlag.c_str())
+ {
+ Utf8Str strKey(strFlag.c_str(), pcszEqual - strFlag.c_str());
+ Utf8Str strValue(strFlag.c_str() + (pcszEqual - strFlag.c_str() + 1));
+
+ if (strKey == "UUID")
+ id = strValue.c_str();
+ else if (strKey == "forceOverwrite")
+ fForceOverwrite = (strValue == "1");
+ else if (strKey == "directoryIncludesUUID")
+ fDirectoryIncludesUUID = (strValue == "1");
+ }
+
+ if (!pcszComma)
+ pcszNext += strFlag.length();
+ else
+ pcszNext += strFlag.length() + 1;
+ }
+ }
+ /* Create UUID if none was specified. */
+ if (id.isEmpty())
+ id.create();
+
/* NULL settings file means compose automatically */
- HRESULT rc;
Bstr bstrSettingsFile(aSettingsFile);
if (bstrSettingsFile.isEmpty())
{
+ Utf8Str strNewCreateFlags(Utf8StrFmt("UUID=%RTuuid", id.raw()));
+ if (fDirectoryIncludesUUID)
+ strNewCreateFlags += ",directoryIncludesUUID=1";
+
rc = ComposeMachineFilename(aName,
- NULL,
+ Bstr(llGroups.front()).raw(),
+ Bstr(strNewCreateFlags).raw(),
+ NULL /* aBaseFolder */,
bstrSettingsFile.asOutParam());
if (FAILED(rc)) return rc;
}
@@ -1380,11 +1672,6 @@ STDMETHODIMP VirtualBox::CreateMachine(IN_BSTR aSettingsFile,
rc = machine.createObject();
if (FAILED(rc)) return rc;
- /* Create UUID if an empty one was specified. */
- Guid id(aId);
- if (id.isEmpty())
- id.create();
-
GuestOSType *osType = NULL;
rc = findGuestOSType(Bstr(aOsTypeId), osType);
if (FAILED(rc)) return rc;
@@ -1393,9 +1680,11 @@ STDMETHODIMP VirtualBox::CreateMachine(IN_BSTR aSettingsFile,
rc = machine->init(this,
Utf8Str(bstrSettingsFile),
Utf8Str(aName),
+ llGroups,
osType,
id,
- !!forceOverwrite);
+ fForceOverwrite,
+ fDirectoryIncludesUUID);
if (SUCCEEDED(rc))
{
/* set the return value */
@@ -1417,7 +1706,7 @@ STDMETHODIMP VirtualBox::OpenMachine(IN_BSTR aSettingsFile,
IMachine **aMachine)
{
CheckComArgStrNotEmptyOrNull(aSettingsFile);
- CheckComArgOutSafeArrayPointerValid(aMachine);
+ CheckComArgOutPointerValid(aMachine);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1430,9 +1719,9 @@ STDMETHODIMP VirtualBox::OpenMachine(IN_BSTR aSettingsFile,
if (SUCCEEDED(rc))
{
/* initialize the machine object */
- rc = machine->init(this,
- aSettingsFile,
- NULL); /* const Guid *aId */
+ rc = machine->initFromSettings(this,
+ aSettingsFile,
+ NULL); /* const Guid *aId */
if (SUCCEEDED(rc))
{
/* set the return value */
@@ -1480,7 +1769,7 @@ STDMETHODIMP VirtualBox::FindMachine(IN_BSTR aNameOrId, IMachine **aMachine)
LogFlowThisFunc(("aName=\"%ls\", aMachine={%p}\n", aNameOrId, aMachine));
CheckComArgStrNotEmptyOrNull(aNameOrId);
- CheckComArgOutSafeArrayPointerValid(aMachine);
+ CheckComArgOutPointerValid(aMachine);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1499,32 +1788,10 @@ STDMETHODIMP VirtualBox::FindMachine(IN_BSTR aNameOrId, IMachine **aMachine)
else
{
Utf8Str strName(aNameOrId);
- AutoReadLock al(m->allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
- for (MachinesOList::iterator it = m->allMachines.begin();
- it != m->allMachines.end();
- ++it)
- {
- ComObjPtr<Machine> &pMachine2 = *it;
- AutoCaller machCaller(pMachine2);
- if (machCaller.rc())
- continue; // we can't ask inaccessible machines for their names
-
- AutoReadLock machLock(pMachine2 COMMA_LOCKVAL_SRC_POS);
- if (pMachine2->getName() == strName)
- {
- pMachineFound = pMachine2;
- break;
- }
- if (!RTPathCompare(pMachine2->getSettingsFileFull().c_str(), strName.c_str()))
- {
- pMachineFound = pMachine2;
- break;
- }
- }
-
- if (!pMachineFound)
- rc = setError(VBOX_E_OBJECT_NOT_FOUND,
- tr("Could not find a registered machine named '%ls'"), aNameOrId);
+ rc = findMachineByName(aNameOrId,
+ true /* setError */,
+ &pMachineFound);
+ // returns VBOX_E_OBJECT_NOT_FOUND if not found and sets error
}
/* this will set (*machine) to NULL if machineObj is null */
@@ -1536,6 +1803,101 @@ STDMETHODIMP VirtualBox::FindMachine(IN_BSTR aNameOrId, IMachine **aMachine)
return rc;
}
+STDMETHODIMP VirtualBox::GetMachinesByGroups(ComSafeArrayIn(IN_BSTR, aGroups), ComSafeArrayOut(IMachine *, aMachines))
+{
+ CheckComArgSafeArrayNotNull(aGroups);
+ CheckComArgOutSafeArrayPointerValid(aMachines);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ StringsList llGroups;
+ HRESULT rc = convertMachineGroups(ComSafeArrayInArg(aGroups), &llGroups);
+ if (FAILED(rc))
+ return rc;
+ /* we want to rely on sorted groups during compare, to save time */
+ llGroups.sort();
+
+ /* get copy of all machine references, to avoid holding the list lock */
+ MachinesOList::MyList allMachines;
+ {
+ AutoReadLock al(m->allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
+ allMachines = m->allMachines.getList();
+ }
+
+ com::SafeIfaceArray<IMachine> saMachines;
+ for (MachinesOList::MyList::const_iterator it = allMachines.begin();
+ it != allMachines.end();
+ ++it)
+ {
+ const ComObjPtr<Machine> &pMachine = *it;
+ AutoCaller autoMachineCaller(pMachine);
+ if (FAILED(autoMachineCaller.rc()))
+ continue;
+ AutoReadLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
+
+ if (pMachine->isAccessible())
+ {
+ const StringsList &thisGroups = pMachine->getGroups();
+ for (StringsList::const_iterator it2 = thisGroups.begin();
+ it2 != thisGroups.end();
+ ++it2)
+ {
+ const Utf8Str &group = *it2;
+ bool fAppended = false;
+ for (StringsList::const_iterator it3 = llGroups.begin();
+ it3 != llGroups.end();
+ ++it3)
+ {
+ int order = it3->compare(group);
+ if (order == 0)
+ {
+ saMachines.push_back(pMachine);
+ fAppended = true;
+ break;
+ }
+ else if (order > 0)
+ break;
+ else
+ continue;
+ }
+ /* avoid duplicates and save time */
+ if (fAppended)
+ break;
+ }
+ }
+ }
+
+ saMachines.detachTo(ComSafeArrayOutArg(aMachines));
+
+ return S_OK;
+}
+
+STDMETHODIMP VirtualBox::GetMachineStates(ComSafeArrayIn(IMachine *, aMachines), ComSafeArrayOut(MachineState_T, aStates))
+{
+ CheckComArgSafeArrayNotNull(aMachines);
+ CheckComArgOutSafeArrayPointerValid(aStates);
+
+ com::SafeIfaceArray<IMachine> saMachines(ComSafeArrayInArg(aMachines));
+ com::SafeArray<MachineState_T> saStates(saMachines.size());
+ for (size_t i = 0; i < saMachines.size(); i++)
+ {
+ ComPtr<IMachine> pMachine = saMachines[i];
+ MachineState_T state = MachineState_Null;
+ if (!pMachine.isNull())
+ {
+ HRESULT rc = pMachine->COMGETTER(State)(&state);
+ if (rc == E_ACCESSDENIED)
+ rc = S_OK;
+ AssertComRC(rc);
+ }
+ saStates[i] = state;
+ }
+ saStates.detachTo(ComSafeArrayOutArg(aStates));
+
+ return S_OK;
+}
+
STDMETHODIMP VirtualBox::CreateHardDisk(IN_BSTR aFormat,
IN_BSTR aLocation,
IMedium **aHardDisk)
@@ -1556,8 +1918,7 @@ STDMETHODIMP VirtualBox::CreateHardDisk(IN_BSTR aFormat,
HRESULT rc = hardDisk->init(this,
format,
aLocation,
- Guid::Empty, // media registry: none yet
- NULL /* pllRegistriesThatNeedSaving */);
+ Guid::Empty /* media registry: none yet */);
if (SUCCEEDED(rc))
hardDisk.queryInterfaceTo(aHardDisk);
@@ -1571,12 +1932,14 @@ STDMETHODIMP VirtualBox::OpenMedium(IN_BSTR aLocation,
BOOL fForceNewUuid,
IMedium **aMedium)
{
+ HRESULT rc = S_OK;
CheckComArgStrNotEmptyOrNull(aLocation);
- CheckComArgOutSafeArrayPointerValid(aMedium);
+ CheckComArgOutPointerValid(aMedium);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ Guid id(aLocation);
ComObjPtr<Medium> pMedium;
// have to get write lock as the whole find/update sequence must be done
@@ -1589,18 +1952,22 @@ STDMETHODIMP VirtualBox::OpenMedium(IN_BSTR aLocation,
switch (deviceType)
{
case DeviceType_HardDisk:
- findHardDiskByLocation(aLocation,
- false, /* aSetError */
- &pMedium);
+ if (!id.isEmpty())
+ rc = findHardDiskById(id, false /* setError */, &pMedium);
+ else
+ rc = findHardDiskByLocation(aLocation,
+ false, /* aSetError */
+ &pMedium);
break;
case DeviceType_Floppy:
case DeviceType_DVD:
- findDVDOrFloppyImage(deviceType,
- NULL, /* guid */
- aLocation,
- false, /* aSetError */
- &pMedium);
+ if (!id.isEmpty())
+ rc = findDVDOrFloppyImage(deviceType, &id, Utf8Str::Empty,
+ false /* setError */, &pMedium);
+ else
+ rc = findDVDOrFloppyImage(deviceType, NULL, aLocation,
+ false /* setError */, &pMedium);
// enforce read-only for DVDs even if caller specified ReadWrite
if (deviceType == DeviceType_DVD)
@@ -1608,11 +1975,9 @@ STDMETHODIMP VirtualBox::OpenMedium(IN_BSTR aLocation,
break;
default:
- return setError(E_INVALIDARG, "Device type must be HardDisk, DVD or Floppy");
+ return setError(E_INVALIDARG, "Device type must be HardDisk, DVD or Floppy %d", deviceType);
}
- HRESULT rc = S_OK;
-
if (pMedium.isNull())
{
pMedium.createObject();
@@ -1626,7 +1991,7 @@ STDMETHODIMP VirtualBox::OpenMedium(IN_BSTR aLocation,
if (SUCCEEDED(rc))
{
- rc = registerMedium(pMedium, &pMedium, deviceType, NULL /* pllRegistriesThatNeedSaving */);
+ rc = registerMedium(pMedium, &pMedium, deviceType);
treeLock.release();
@@ -1635,8 +2000,13 @@ STDMETHODIMP VirtualBox::OpenMedium(IN_BSTR aLocation,
* with the parent and this association needs to be broken. */
if (FAILED(rc))
+ {
pMedium->uninit();
+ rc = VBOX_E_OBJECT_NOT_FOUND;
+ }
}
+ else
+ rc = VBOX_E_OBJECT_NOT_FOUND;
}
if (SUCCEEDED(rc))
@@ -1645,88 +2015,15 @@ STDMETHODIMP VirtualBox::OpenMedium(IN_BSTR aLocation,
return rc;
}
-STDMETHODIMP VirtualBox::FindMedium(IN_BSTR aLocation,
- DeviceType_T aDeviceType,
- IMedium **aMedium)
-{
- CheckComArgStrNotEmptyOrNull(aLocation);
- CheckComArgOutSafeArrayPointerValid(aMedium);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- Guid id(aLocation);
- Utf8Str strLocation(aLocation);
-
- HRESULT rc;
- ComObjPtr<Medium> pMedium;
-
- switch (aDeviceType)
- {
- case DeviceType_HardDisk:
- if (!id.isEmpty())
- rc = findHardDiskById(id, true /* setError */, &pMedium);
- else
- rc = findHardDiskByLocation(strLocation, true /* setError */, &pMedium);
- break;
-
- case DeviceType_Floppy:
- case DeviceType_DVD:
- if (!id.isEmpty())
- rc = findDVDOrFloppyImage(aDeviceType, &id, Utf8Str::Empty, true /* setError */, &pMedium);
- else
- rc = findDVDOrFloppyImage(aDeviceType, NULL, strLocation, true /* setError */, &pMedium);
- break;
-
- default:
- return setError(E_INVALIDARG,
- tr("Invalid device type %d"), aDeviceType);
- }
-
- /* the below will set *aHardDisk to NULL if hardDisk is null */
- pMedium.queryInterfaceTo(aMedium);
-
- return rc;
-}
/** @note Locks this object for reading. */
STDMETHODIMP VirtualBox::GetGuestOSType(IN_BSTR aId, IGuestOSType **aType)
{
- /* Old ID to new ID conversion table. See r39691 for a source */
- static const wchar_t *kOldNewIDs[] =
- {
- L"unknown", L"Other",
- L"win31", L"Windows31",
- L"win95", L"Windows95",
- L"win98", L"Windows98",
- L"winme", L"WindowsMe",
- L"winnt4", L"WindowsNT4",
- L"win2k", L"Windows2000",
- L"winxp", L"WindowsXP",
- L"win2k3", L"Windows2003",
- L"winvista", L"WindowsVista",
- L"win2k8", L"Windows2008",
- L"ecs", L"OS2eCS",
- L"fedoracore", L"Fedora",
- /* the rest is covered by the case-insensitive comparison */
- };
-
CheckComArgNotNull(aType);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
- /* first, look for a substitution */
- Bstr id = aId;
- for (size_t i = 0; i < RT_ELEMENTS(kOldNewIDs) / 2; i += 2)
- {
- if (id == kOldNewIDs[i])
- {
- id = kOldNewIDs[i + 1];
- break;
- }
- }
-
*aType = NULL;
AutoReadLock alock(m->allGuestOSTypes.getLockHandle() COMMA_LOCKVAL_SRC_POS);
@@ -1736,7 +2033,7 @@ STDMETHODIMP VirtualBox::GetGuestOSType(IN_BSTR aId, IGuestOSType **aType)
{
const Bstr &typeId = (*it)->id();
AssertMsg(!typeId.isEmpty(), ("ID must not be NULL"));
- if (typeId.compare(id, Bstr::CaseInsensitive) == 0)
+ if (typeId.compare(aId, Bstr::CaseInsensitive) == 0)
{
(*it).queryInterfaceTo(aType);
break;
@@ -1778,8 +2075,7 @@ STDMETHODIMP VirtualBox::GetExtraDataKeys(ComSafeArrayOut(BSTR, aKeys))
{
using namespace settings;
- if (ComSafeArrayOutIsNull(aKeys))
- return E_POINTER;
+ CheckComArgOutSafeArrayPointerValid(aKeys);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -1902,6 +2198,220 @@ STDMETHODIMP VirtualBox::SetExtraData(IN_BSTR aKey,
return S_OK;
}
+/**
+ *
+ */
+STDMETHODIMP VirtualBox::SetSettingsSecret(IN_BSTR aValue)
+{
+ storeSettingsKey(aValue);
+ decryptSettings();
+ return S_OK;
+}
+
+int VirtualBox::decryptMediumSettings(Medium *pMedium)
+{
+ Bstr bstrCipher;
+ HRESULT hrc = pMedium->GetProperty(Bstr("InitiatorSecretEncrypted").raw(),
+ bstrCipher.asOutParam());
+ if (SUCCEEDED(hrc))
+ {
+ Utf8Str strPlaintext;
+ int rc = decryptSetting(&strPlaintext, bstrCipher);
+ if (RT_SUCCESS(rc))
+ pMedium->setPropertyDirect("InitiatorSecret", strPlaintext);
+ else
+ return rc;
+ }
+ return VINF_SUCCESS;
+}
+
+/**
+ * Decrypt all encrypted settings.
+ *
+ * So far we only have encrypted iSCSI initiator secrets so we just go through
+ * all hard disk mediums and determine the plain 'InitiatorSecret' from
+ * 'InitiatorSecretEncrypted. The latter is stored as Base64 because medium
+ * properties need to be null-terminated strings.
+ */
+int VirtualBox::decryptSettings()
+{
+ bool fFailure = false;
+ AutoReadLock al(m->allHardDisks.getLockHandle() COMMA_LOCKVAL_SRC_POS);
+ for (MediaList::const_iterator mt = m->allHardDisks.begin();
+ mt != m->allHardDisks.end();
+ ++mt)
+ {
+ ComObjPtr<Medium> pMedium = *mt;
+ AutoCaller medCaller(pMedium);
+ if (FAILED(medCaller.rc()))
+ continue;
+ AutoWriteLock mlock(pMedium COMMA_LOCKVAL_SRC_POS);
+ int vrc = decryptMediumSettings(pMedium);
+ if (RT_FAILURE(vrc))
+ fFailure = true;
+ }
+ return fFailure ? VERR_INVALID_PARAMETER : VINF_SUCCESS;
+}
+
+/**
+ * Encode.
+ *
+ * @param aPlaintext plaintext to be encrypted
+ * @param aCiphertext resulting ciphertext (base64-encoded)
+ */
+int VirtualBox::encryptSetting(const Utf8Str &aPlaintext, Utf8Str *aCiphertext)
+{
+ uint8_t abCiphertext[32];
+ char szCipherBase64[128];
+ size_t cchCipherBase64;
+ int rc = encryptSettingBytes((uint8_t*)aPlaintext.c_str(), abCiphertext,
+ aPlaintext.length()+1, sizeof(abCiphertext));
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTBase64Encode(abCiphertext, sizeof(abCiphertext),
+ szCipherBase64, sizeof(szCipherBase64),
+ &cchCipherBase64);
+ if (RT_SUCCESS(rc))
+ *aCiphertext = szCipherBase64;
+ }
+ return rc;
+}
+
+/**
+ * Decode.
+ *
+ * @param aPlaintext resulting plaintext
+ * @param aCiphertext ciphertext (base64-encoded) to decrypt
+ */
+int VirtualBox::decryptSetting(Utf8Str *aPlaintext, const Utf8Str &aCiphertext)
+{
+ uint8_t abPlaintext[64];
+ uint8_t abCiphertext[64];
+ size_t cbCiphertext;
+ int rc = RTBase64Decode(aCiphertext.c_str(),
+ abCiphertext, sizeof(abCiphertext),
+ &cbCiphertext, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = decryptSettingBytes(abPlaintext, abCiphertext, cbCiphertext);
+ if (RT_SUCCESS(rc))
+ {
+ for (unsigned i = 0; i < cbCiphertext; i++)
+ {
+ /* sanity check: null-terminated string? */
+ if (abPlaintext[i] == '\0')
+ {
+ /* sanity check: valid UTF8 string? */
+ if (RTStrIsValidEncoding((const char*)abPlaintext))
+ {
+ *aPlaintext = Utf8Str((const char*)abPlaintext);
+ return VINF_SUCCESS;
+ }
+ }
+ }
+ rc = VERR_INVALID_MAGIC;
+ }
+ }
+ return rc;
+}
+
+/**
+ * Encrypt secret bytes. Use the m->SettingsCipherKey as key.
+ *
+ * @param aPlaintext clear text to be encrypted
+ * @param aCiphertext resulting encrypted text
+ * @param aPlaintextSize size of the plaintext
+ * @param aCiphertextSize size of the ciphertext
+ */
+int VirtualBox::encryptSettingBytes(const uint8_t *aPlaintext, uint8_t *aCiphertext,
+ size_t aPlaintextSize, size_t aCiphertextSize) const
+{
+ unsigned i, j;
+ uint8_t aBytes[64];
+
+ if (!m->fSettingsCipherKeySet)
+ return VERR_INVALID_STATE;
+
+ if (aCiphertextSize > sizeof(aBytes))
+ return VERR_BUFFER_OVERFLOW;
+
+ if (aCiphertextSize < 32)
+ return VERR_INVALID_PARAMETER;
+
+ AssertCompile(sizeof(m->SettingsCipherKey) >= 32);
+
+ /* store the first 8 bytes of the cipherkey for verification */
+ for (i = 0, j = 0; i < 8; i++, j++)
+ aCiphertext[i] = m->SettingsCipherKey[j];
+
+ for (unsigned k = 0; k < aPlaintextSize && i < aCiphertextSize; i++, k++)
+ {
+ aCiphertext[i] = (aPlaintext[k] ^ m->SettingsCipherKey[j]);
+ if (++j >= sizeof(m->SettingsCipherKey))
+ j = 0;
+ }
+
+ /* fill with random data to have a minimal length (salt) */
+ if (i < aCiphertextSize)
+ {
+ RTRandBytes(aBytes, aCiphertextSize - i);
+ for (int k = 0; i < aCiphertextSize; i++, k++)
+ {
+ aCiphertext[i] = aBytes[k] ^ m->SettingsCipherKey[j];
+ if (++j >= sizeof(m->SettingsCipherKey))
+ j = 0;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Decrypt secret bytes. Use the m->SettingsCipherKey as key.
+ *
+ * @param aPlaintext resulting plaintext
+ * @param aCiphertext ciphertext to be decrypted
+ * @param aCiphertextSize size of the ciphertext == size of the plaintext
+ */
+int VirtualBox::decryptSettingBytes(uint8_t *aPlaintext,
+ const uint8_t *aCiphertext, size_t aCiphertextSize) const
+{
+ unsigned i, j;
+
+ if (!m->fSettingsCipherKeySet)
+ return VERR_INVALID_STATE;
+
+ if (aCiphertextSize < 32)
+ return VERR_INVALID_PARAMETER;
+
+ /* key verification */
+ for (i = 0, j = 0; i < 8; i++, j++)
+ if (aCiphertext[i] != m->SettingsCipherKey[j])
+ return VERR_INVALID_MAGIC;
+
+ /* poison */
+ memset(aPlaintext, 0xff, aCiphertextSize);
+ for (int k = 0; i < aCiphertextSize; i++, k++)
+ {
+ aPlaintext[k] = aCiphertext[i] ^ m->SettingsCipherKey[j];
+ if (++j >= sizeof(m->SettingsCipherKey))
+ j = 0;
+ }
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Store a settings key.
+ *
+ * @param aKey the key to store
+ */
+void VirtualBox::storeSettingsKey(const Utf8Str &aKey)
+{
+ RTSha512(aKey.c_str(), aKey.length(), m->SettingsCipherKey);
+ m->fSettingsCipherKeySet = true;
+}
+
// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
@@ -2280,6 +2790,7 @@ void VirtualBox::updateClientWatcher()
#elif defined(RT_OS_OS2)
RTSemEventSignal(m->updateReq);
#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
+ ASMAtomicUoWriteU8(&m->updateAdaptCtr, RT_ELEMENTS(s_updateAdaptTimeouts) - 1);
RTSemEventSignal(m->updateReq);
#else
# error "Port me!"
@@ -2470,8 +2981,8 @@ struct SnapshotEvent : public VirtualBox::CallbackEvent
virtual HRESULT prepareEventDesc(IEventSource* aSource, VBoxEventDesc& aEvDesc)
{
- return aEvDesc.init(aSource, VBoxEventType_OnSnapshotTaken,
- machineId.toUtf16().raw(), snapshotId.toUtf16().raw());
+ return aEvDesc.init(aSource, mWhat, machineId.toUtf16().raw(),
+ snapshotId.toUtf16().raw());
}
Guid machineId;
@@ -2681,21 +3192,21 @@ HRESULT VirtualBox::findMachine(const Guid &aId,
it != m->allMachines.end();
++it)
{
- ComObjPtr<Machine> pMachine2 = *it;
+ ComObjPtr<Machine> pMachine = *it;
if (!fPermitInaccessible)
{
// skip inaccessible machines
- AutoCaller machCaller(pMachine2);
+ AutoCaller machCaller(pMachine);
if (FAILED(machCaller.rc()))
continue;
}
- if (pMachine2->getId() == aId)
+ if (pMachine->getId() == aId)
{
rc = S_OK;
if (aMachine)
- *aMachine = pMachine2;
+ *aMachine = pMachine;
break;
}
}
@@ -2710,6 +3221,175 @@ HRESULT VirtualBox::findMachine(const Guid &aId,
}
/**
+ * Searches for a machine object with the given name or location in the
+ * collection of registered machines.
+ *
+ * @param aName Machine name or location to look for.
+ * @param aSetError If true, set errorinfo if the machine is not found.
+ * @param aMachine Returned machine, if found.
+ * @return
+ */
+HRESULT VirtualBox::findMachineByName(const Utf8Str &aName, bool aSetError,
+ ComObjPtr<Machine> *aMachine /* = NULL */)
+{
+ HRESULT rc = VBOX_E_OBJECT_NOT_FOUND;
+
+ AutoReadLock al(m->allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
+ for (MachinesOList::iterator it = m->allMachines.begin();
+ it != m->allMachines.end();
+ ++it)
+ {
+ ComObjPtr<Machine> &pMachine = *it;
+ AutoCaller machCaller(pMachine);
+ if (machCaller.rc())
+ continue; // we can't ask inaccessible machines for their names
+
+ AutoReadLock machLock(pMachine COMMA_LOCKVAL_SRC_POS);
+ if (pMachine->getName() == aName)
+ {
+ rc = S_OK;
+ if (aMachine)
+ *aMachine = pMachine;
+ break;
+ }
+ if (!RTPathCompare(pMachine->getSettingsFileFull().c_str(), aName.c_str()))
+ {
+ rc = S_OK;
+ if (aMachine)
+ *aMachine = pMachine;
+ break;
+ }
+ }
+
+ if (aSetError && FAILED(rc))
+ rc = setError(rc,
+ tr("Could not find a registered machine named '%s'"), aName.c_str());
+
+ return rc;
+}
+
+static HRESULT validateMachineGroupHelper(const Utf8Str &aGroup, bool fPrimary, VirtualBox *pVirtualBox)
+{
+ /* empty strings are invalid */
+ if (aGroup.isEmpty())
+ return E_INVALIDARG;
+ /* the toplevel group is valid */
+ if (aGroup == "/")
+ return S_OK;
+ /* any other strings of length 1 are invalid */
+ if (aGroup.length() == 1)
+ return E_INVALIDARG;
+ /* must start with a slash */
+ if (aGroup.c_str()[0] != '/')
+ return E_INVALIDARG;
+ /* must not end with a slash */
+ if (aGroup.c_str()[aGroup.length() - 1] == '/')
+ return E_INVALIDARG;
+ /* check the group components */
+ const char *pStr = aGroup.c_str() + 1; /* first char is /, skip it */
+ while (pStr)
+ {
+ char *pSlash = RTStrStr(pStr, "/");
+ if (pSlash)
+ {
+ /* no empty components (or // sequences in other words) */
+ if (pSlash == pStr)
+ return E_INVALIDARG;
+ /* check if the machine name rules are violated, because that means
+ * the group components are too close to the limits. */
+ Utf8Str tmp((const char *)pStr, (size_t)(pSlash - pStr));
+ Utf8Str tmp2(tmp);
+ sanitiseMachineFilename(tmp);
+ if (tmp != tmp2)
+ return E_INVALIDARG;
+ if (fPrimary)
+ {
+ HRESULT rc = pVirtualBox->findMachineByName(tmp,
+ false /* aSetError */);
+ if (SUCCEEDED(rc))
+ return VBOX_E_VM_ERROR;
+ }
+ pStr = pSlash + 1;
+ }
+ else
+ {
+ /* check if the machine name rules are violated, because that means
+ * the group components is too close to the limits. */
+ Utf8Str tmp(pStr);
+ Utf8Str tmp2(tmp);
+ sanitiseMachineFilename(tmp);
+ if (tmp != tmp2)
+ return E_INVALIDARG;
+ pStr = NULL;
+ }
+ }
+ return S_OK;
+}
+
+/**
+ * Validates a machine group.
+ *
+ * @param aMachineGroup Machine group.
+ * @param fPrimary Set if this is the primary group.
+ *
+ * @return S_OK or E_INVALIDARG
+ */
+HRESULT VirtualBox::validateMachineGroup(const Utf8Str &aGroup, bool fPrimary)
+{
+ HRESULT rc = validateMachineGroupHelper(aGroup, fPrimary, this);
+ if (FAILED(rc))
+ {
+ if (rc == VBOX_E_VM_ERROR)
+ rc = setError(E_INVALIDARG,
+ tr("Machine group '%s' conflicts with a virtual machine name"),
+ aGroup.c_str());
+ else
+ rc = setError(rc,
+ tr("Invalid machine group '%s'"),
+ aGroup.c_str());
+ }
+ return rc;
+}
+
+/**
+ * Takes a list of machine groups, and sanitizes/validates it.
+ *
+ * @param aMachineGroups Safearray with the machine groups.
+ * @param pllMachineGroups Pointer to list of strings for the result.
+ *
+ * @return S_OK or E_INVALIDARG
+ */
+HRESULT VirtualBox::convertMachineGroups(ComSafeArrayIn(IN_BSTR, aMachineGroups), StringsList *pllMachineGroups)
+{
+ pllMachineGroups->clear();
+ if (aMachineGroups)
+ {
+ com::SafeArray<IN_BSTR> machineGroups(ComSafeArrayInArg(aMachineGroups));
+ for (size_t i = 0; i < machineGroups.size(); i++)
+ {
+ Utf8Str group(machineGroups[i]);
+ if (group.length() == 0)
+ group = "/";
+
+ HRESULT rc = validateMachineGroup(group, i == 0);
+ if (FAILED(rc))
+ return rc;
+
+ /* no duplicates please */
+ if ( find(pllMachineGroups->begin(), pllMachineGroups->end(), group)
+ == pllMachineGroups->end())
+ pllMachineGroups->push_back(group);
+ }
+ if (pllMachineGroups->size() == 0)
+ pllMachineGroups->push_back("/");
+ }
+ else
+ pllMachineGroups->push_back("/");
+
+ return S_OK;
+}
+
+/**
* Searches for a Medium object with the given ID in the list of registered
* hard disks.
*
@@ -3021,6 +3701,14 @@ ExtPackManager* VirtualBox::getExtPackManager() const
}
#endif
+/**
+ * Getter that machines can talk to the autostart database.
+ */
+AutostartDb* VirtualBox::getAutostartDb() const
+{
+ return m->pAutostartDb;
+}
+
#ifdef VBOX_WITH_RESOURCE_USAGE_API
const ComObjPtr<PerformanceCollector>& VirtualBox::performanceCollector() const
{
@@ -3213,6 +3901,39 @@ void VirtualBox::rememberMachineNameChangeForMedia(const Utf8Str &strOldConfigDi
m->llPendingMachineRenames.push_back(pmr);
}
+struct SaveMediaRegistriesDesc
+{
+ MediaList llMedia;
+ ComObjPtr<VirtualBox> pVirtualBox;
+};
+
+static int fntSaveMediaRegistries(RTTHREAD ThreadSelf, void *pvUser)
+{
+ NOREF(ThreadSelf);
+ SaveMediaRegistriesDesc *pDesc = (SaveMediaRegistriesDesc *)pvUser;
+ if (!pDesc)
+ {
+ LogRelFunc(("Thread for saving media registries lacks parameters\n"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ for (MediaList::const_iterator it = pDesc->llMedia.begin();
+ it != pDesc->llMedia.end();
+ ++it)
+ {
+ Medium *pMedium = *it;
+ pMedium->markRegistriesModified();
+ }
+
+ pDesc->pVirtualBox->saveModifiedRegistries();
+
+ pDesc->llMedia.clear();
+ pDesc->pVirtualBox.setNull();
+ delete pDesc;
+
+ return VINF_SUCCESS;
+}
+
/**
* Goes through all known media (hard disks, floppies and DVDs) and saves
* those into the given settings::MediaRegistry structures whose registry
@@ -3240,7 +3961,7 @@ void VirtualBox::rememberMachineNameChangeForMedia(const Utf8Str &strOldConfigDi
*
* @param mediaRegistry Settings structure to fill.
* @param uuidRegistry The UUID of the media registry; either a machine UUID (if machine registry) or the UUID of the global registry.
- * @param hardDiskFolder The machine folder for relative paths, if machine registry, or an empty string otherwise.
+ * @param strMachineFolder The machine folder for relative paths, if machine registry, or an empty string otherwise.
*/
void VirtualBox::saveMediaRegistry(settings::MediaRegistry &mediaRegistry,
const Guid &uuidRegistry,
@@ -3263,6 +3984,7 @@ void VirtualBox::saveMediaRegistry(settings::MediaRegistry &mediaRegistry,
for (MediaList::iterator it = m->allFloppyImages.begin(); it != m->allFloppyImages.end(); ++it)
llAllMedia.push_back(*it);
+ SaveMediaRegistriesDesc *pDesc = new SaveMediaRegistriesDesc();
for (MediaList::iterator it = llAllMedia.begin();
it != llAllMedia.end();
++it)
@@ -3273,12 +3995,47 @@ void VirtualBox::saveMediaRegistry(settings::MediaRegistry &mediaRegistry,
++it2)
{
const Data::PendingMachineRename &pmr = *it2;
- pMedium->updatePath(pmr.strConfigDirOld,
- pmr.strConfigDirNew);
+ HRESULT rc = pMedium->updatePath(pmr.strConfigDirOld,
+ pmr.strConfigDirNew);
+ if (SUCCEEDED(rc))
+ {
+ // Remember which medium objects has been changed,
+ // to trigger saving their registries later.
+ pDesc->llMedia.push_back(pMedium);
+ } else if (rc == VBOX_E_FILE_ERROR)
+ /* nothing */;
+ else
+ AssertComRC(rc);
}
}
// done, don't do it again until we have more machine renames
m->llPendingMachineRenames.clear();
+
+ if (pDesc->llMedia.size())
+ {
+ // Handle the media registry saving in a separate thread, to
+ // avoid giant locking problems and passing up the list many
+ // levels up to whoever triggered saveSettings, as there are
+ // lots of places which would need to handle saving more settings.
+ pDesc->pVirtualBox = this;
+ int vrc = RTThreadCreate(NULL,
+ fntSaveMediaRegistries,
+ (void *)pDesc,
+ 0, // cbStack (default)
+ RTTHREADTYPE_MAIN_WORKER,
+ 0, // flags
+ "SaveMediaReg");
+ ComAssertRC(vrc);
+ // failure means that settings aren't saved, but there isn't
+ // much we can do besides avoiding memory leaks
+ if (RT_FAILURE(vrc))
+ {
+ LogRelFunc(("Failed to create thread for saving media registries (%Rrc)\n", vrc));
+ delete pDesc;
+ }
+ }
+ else
+ delete pDesc;
}
struct {
@@ -3395,7 +4152,7 @@ HRESULT VirtualBox::saveSettings()
}
catch (...)
{
- rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
+ rc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
}
return rc;
@@ -3468,20 +4225,19 @@ HRESULT VirtualBox::registerMachine(Machine *aMachine)
* Remembers the given medium object by storing it in either the global
* medium registry or a machine one.
*
- * @note Caller must hold the media tree lock for writing; in addition, this locks @a pMedium for reading
+ * @note Caller must hold the media tree lock for writing; in addition, this
+ * locks @a pMedium for reading
*
* @param pMedium Medium object to remember.
* @param ppMedium Actually stored medium object. Can be different if due
* to an unavoidable race there was a duplicate Medium object
* created.
* @param argType Either DeviceType_HardDisk, DeviceType_DVD or DeviceType_Floppy.
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving.
* @return
*/
HRESULT VirtualBox::registerMedium(const ComObjPtr<Medium> &pMedium,
ComObjPtr<Medium> *ppMedium,
- DeviceType_T argType,
- GuidList *pllRegistriesThatNeedSaving)
+ DeviceType_T argType)
{
AssertReturn(pMedium != NULL, E_INVALIDARG);
AssertReturn(ppMedium != NULL, E_INVALIDARG);
@@ -3555,11 +4311,6 @@ HRESULT VirtualBox::registerMedium(const ComObjPtr<Medium> &pMedium,
m->mapHardDisks[id] = pMedium;
*ppMedium = pMedium;
-
- if (pllRegistriesThatNeedSaving)
- pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
-
- *ppMedium = pMedium;
}
else
{
@@ -3569,9 +4320,6 @@ HRESULT VirtualBox::registerMedium(const ComObjPtr<Medium> &pMedium,
// have a caller pending.
mediumCaller.release();
*ppMedium = pDupMedium;
-
- // no need to update pllRegistriesThatNeedSaving since there must be
- // already some saved medium registry which contains the data.
}
return rc;
@@ -3580,13 +4328,11 @@ HRESULT VirtualBox::registerMedium(const ComObjPtr<Medium> &pMedium,
/**
* Removes the given medium from the respective registry.
*
- * @param pMedium Hard disk object to remove.
- * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving.
+ * @param pMedium Hard disk object to remove.
*
* @note Caller must hold the media tree lock for writing; in addition, this locks @a pMedium for reading
*/
-HRESULT VirtualBox::unregisterMedium(Medium *pMedium,
- GuidList *pllRegistriesThatNeedSaving)
+HRESULT VirtualBox::unregisterMedium(Medium *pMedium)
{
AssertReturn(pMedium != NULL, E_INVALIDARG);
@@ -3637,9 +4383,6 @@ HRESULT VirtualBox::unregisterMedium(Medium *pMedium,
NOREF(cnt);
}
- if (pllRegistriesThatNeedSaving)
- pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
-
return S_OK;
}
@@ -3713,7 +4456,7 @@ HRESULT VirtualBox::unregisterMachineMedia(const Guid &uuidMachine)
ComObjPtr<Medium> pMedium = *it;
Log(("Closing medium %RTuuid\n", pMedium->getId().raw()));
AutoCaller mac(pMedium);
- pMedium->close(NULL /* pllRegistriesThatNeedSaving */, mac);
+ pMedium->close(mac);
}
LogFlowFuncLeave();
@@ -3749,7 +4492,6 @@ HRESULT VirtualBox::unregisterMachine(Machine *pMachine,
* A is deleted, A.vdi must be moved to the registry of B, or else B will
* become inaccessible.
*/
- GuidList llRegistriesThatNeedSaving;
{
AutoReadLock tlock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
// iterate over the list of *base* images
@@ -3773,13 +4515,17 @@ HRESULT VirtualBox::unregisterMachine(Machine *pMachine,
// 2) better registry found: then use that
pMedium->addRegistry(*puuidBetter, true /* fRecurse */);
// 3) and make sure the registry is saved below
- VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, *puuidBetter);
+ mlock.release();
+ tlock.release();
+ markRegistryModified(*puuidBetter);
+ tlock.acquire();
+ mlock.release();
}
}
}
}
- saveRegistries(llRegistriesThatNeedSaving);
+ saveModifiedRegistries();
/* fire an event */
onMachineRegistered(id, FALSE);
@@ -3788,81 +4534,100 @@ HRESULT VirtualBox::unregisterMachine(Machine *pMachine,
}
/**
- * Adds uuid to llRegistriesThatNeedSaving unless it's already on the list.
- *
- * @todo maybe there's something in libstdc++ for this
+ * Marks the registry for @a uuid as modified, so that it's saved in a later
+ * call to saveModifiedRegistries().
*
- * @param llRegistriesThatNeedSaving
* @param uuid
*/
-/* static */
-void VirtualBox::addGuidToListUniquely(GuidList &llRegistriesThatNeedSaving,
- const Guid &uuid)
+void VirtualBox::markRegistryModified(const Guid &uuid)
{
- for (GuidList::const_iterator it = llRegistriesThatNeedSaving.begin();
- it != llRegistriesThatNeedSaving.end();
- ++it)
+ if (uuid == getGlobalRegistryId())
+ ASMAtomicIncU64(&m->uRegistryNeedsSaving);
+ else
{
- if (*it == uuid)
- // uuid is already in list:
- return;
+ ComObjPtr<Machine> pMachine;
+ HRESULT rc = findMachine(uuid,
+ false /* fPermitInaccessible */,
+ false /* aSetError */,
+ &pMachine);
+ if (SUCCEEDED(rc))
+ {
+ AutoCaller machineCaller(pMachine);
+ if (SUCCEEDED(machineCaller.rc()))
+ ASMAtomicIncU64(&pMachine->uRegistryNeedsSaving);
+ }
}
-
- llRegistriesThatNeedSaving.push_back(uuid);
}
/**
- * Saves all settings files according to the given list of UUIDs, which are
- * either machine IDs (in which case Machine::saveSettings is invoked) or
- * the global registry UUID (in which case VirtualBox::saveSettings is invoked).
+ * Saves all settings files according to the modified flags in the Machine
+ * objects and in the VirtualBox object.
*
* This locks machines and the VirtualBox object as necessary, so better not
* hold any locks before calling this.
*
- * @param llRegistriesThatNeedSaving
+ * @return
*/
-void VirtualBox::saveRegistries(const GuidList &llRegistriesThatNeedSaving)
+void VirtualBox::saveModifiedRegistries()
{
- bool fNeedsGlobalSettings = false;
HRESULT rc = S_OK;
+ bool fNeedsGlobalSettings = false;
+ uint64_t uOld;
- for (GuidList::const_iterator it = llRegistriesThatNeedSaving.begin();
- it != llRegistriesThatNeedSaving.end();
- ++it)
{
- const Guid &uuid = *it;
-
- if (uuid == getGlobalRegistryId())
- fNeedsGlobalSettings = true;
- else
+ AutoReadLock alock(m->allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
+ for (MachinesOList::iterator it = m->allMachines.begin();
+ it != m->allMachines.end();
+ ++it)
{
- // should be machine ID then:
- ComObjPtr<Machine> pMachine;
- rc = findMachine(uuid,
- false /* fPermitInaccessible */,
- false /* aSetError */,
- &pMachine);
- if (SUCCEEDED(rc))
+ const ComObjPtr<Machine> &pMachine = *it;
+
+ for (;;)
+ {
+ uOld = ASMAtomicReadU64(&pMachine->uRegistryNeedsSaving);
+ if (!uOld)
+ break;
+ if (ASMAtomicCmpXchgU64(&pMachine->uRegistryNeedsSaving, 0, uOld))
+ break;
+ ASMNopPause();
+ }
+ if (uOld)
{
AutoCaller autoCaller(pMachine);
- if (FAILED(autoCaller.rc())) continue;
+ if (FAILED(autoCaller.rc()))
+ continue;
+ /* object is already dead, no point in saving settings */
+ if (autoCaller.state() != Ready)
+ continue;
AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
rc = pMachine->saveSettings(&fNeedsGlobalSettings,
Machine::SaveS_Force); // caller said save, so stop arguing
}
-
- // There are inherent races (the VM where the media registry was
- // when the list was created has been deleted in the mean time),
- // so do not thread a failure at findMachine as fatal. Likewise
- // saveSettings can fail if the machine has been uninitialized.
}
}
- if (fNeedsGlobalSettings)
+ for (;;)
{
- AutoWriteLock vlock(this COMMA_LOCKVAL_SRC_POS);
+ uOld = ASMAtomicReadU64(&m->uRegistryNeedsSaving);
+ if (!uOld)
+ break;
+ if (ASMAtomicCmpXchgU64(&m->uRegistryNeedsSaving, 0, uOld))
+ break;
+ ASMNopPause();
+ }
+ if (uOld || fNeedsGlobalSettings)
+ {
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
rc = saveSettings();
}
+ NOREF(rc); /* XXX */
+}
+
+
+/* static */
+const Bstr &VirtualBox::getVersionNormalized()
+{
+ return sVersionNormalized;
}
/**
@@ -3903,62 +4668,6 @@ HRESULT VirtualBox::ensureFilePathExists(const Utf8Str &strFileName, bool fCreat
return S_OK;
}
-/**
- * Handles unexpected exceptions by turning them into COM errors in release
- * builds or by hitting a breakpoint in the release builds.
- *
- * Usage pattern:
- * @code
- try
- {
- // ...
- }
- catch (LaLalA)
- {
- // ...
- }
- catch (...)
- {
- rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS);
- }
- * @endcode
- *
- * @param RT_SRC_POS_DECL "RT_SRC_POS" macro instantiation.
- */
-/* static */
-HRESULT VirtualBox::handleUnexpectedExceptions(RT_SRC_POS_DECL)
-{
- try
- {
- /* re-throw the current exception */
- throw;
- }
- catch (const RTCError &err) // includes all XML exceptions
- {
- return setErrorStatic(E_FAIL,
- Utf8StrFmt(tr("%s.\n%s[%d] (%s)"),
- err.what(),
- pszFile, iLine, pszFunction).c_str());
- }
- catch (const std::exception &err)
- {
- return setErrorStatic(E_FAIL,
- Utf8StrFmt(tr("Unexpected exception: %s [%s]\n%s[%d] (%s)"),
- err.what(), typeid(err).name(),
- pszFile, iLine, pszFunction).c_str());
- }
- catch (...)
- {
- return setErrorStatic(E_FAIL,
- Utf8StrFmt(tr("Unknown exception\n%s[%d] (%s)"),
- pszFile, iLine, pszFunction).c_str());
- }
-
- /* should not get here */
- AssertFailed();
- return E_FAIL;
-}
-
const Utf8Str& VirtualBox::settingsFilePath()
{
return m->strSettingsFilePath;
@@ -4342,7 +5051,24 @@ DECLCALLBACK(int) VirtualBox::ClientWatcher(RTTHREAD /* thread */, void *pvUser)
/* release the caller to let uninit() ever proceed */
autoCaller.release();
- int rc = RTSemEventWait(that->m->updateReq, 500);
+ /* determine wait timeout adaptively: after updating information
+ * relevant to the client watcher, check a few times more
+ * frequently. This ensures good reaction time when the signalling
+ * has to be done a bit before the actual change for technical
+ * reasons, and saves CPU cycles when no activities are expected. */
+ RTMSINTERVAL cMillies;
+ {
+ uint8_t uOld, uNew;
+ do
+ {
+ uOld = ASMAtomicUoReadU8(&that->m->updateAdaptCtr);
+ uNew = uOld ? uOld - 1 : uOld;
+ } while (!ASMAtomicCmpXchgU8(&that->m->updateAdaptCtr, uNew, uOld));
+ Assert(uOld <= RT_ELEMENTS(s_updateAdaptTimeouts) - 1);
+ cMillies = s_updateAdaptTimeouts[uOld];
+ }
+
+ int rc = RTSemEventWait(that->m->updateReq, cMillies);
/*
* Restore the caller before using VirtualBox. If it fails, this
@@ -4483,7 +5209,7 @@ DECLCALLBACK(int) VirtualBox::AsyncEventHandler(RTTHREAD thread, void *pvUser)
* In case of spurious wakeups causing VERR_TIMEOUTs and/or other return codes
* we must not stop processing events and delete the "eventQ" object. This must
* be done ONLY when we stop this loop via interruptEventQueueProcessing().
- * See #5724.
+ * See @bugref{5724}.
*/
while (eventQ->processEventQueue(RT_INDEFINITE_WAIT) != VERR_INTERRUPTED)
/* nothing */ ;
@@ -4608,12 +5334,12 @@ STDMETHODIMP VirtualBox::RemoveDHCPServer(IDHCPServer * aServer)
}
/**
- * Remembers the given dhcp server by storing it in the hard disk registry.
+ * Remembers the given DHCP server in the settings.
*
- * @param aDHCPServer Dhcp Server object to remember.
- * @param aSaveRegistry @c true to save hard disk registry to disk (default).
+ * @param aDHCPServer DHCP server object to remember.
+ * @param aSaveSettings @c true to save settings to disk (default).
*
- * When @a aSaveRegistry is @c true, this operation may fail because of the
+ * When @a aSaveSettings is @c true, this operation may fail because of the
* failed #saveSettings() method it calls. In this case, the dhcp server object
* will not be remembered. It is therefore the responsibility of the caller to
* call this method as the last step of some action that requires registration
@@ -4623,7 +5349,7 @@ STDMETHODIMP VirtualBox::RemoveDHCPServer(IDHCPServer * aServer)
* @note Locks this object for writing and @a aDHCPServer for reading.
*/
HRESULT VirtualBox::registerDHCPServer(DHCPServer *aDHCPServer,
- bool aSaveRegistry /*= true*/)
+ bool aSaveSettings /*= true*/)
{
AssertReturn(aDHCPServer != NULL, E_INVALIDARG);
@@ -4647,36 +5373,33 @@ HRESULT VirtualBox::registerDHCPServer(DHCPServer *aDHCPServer,
m->allDHCPServers.addChild(aDHCPServer);
- if (aSaveRegistry)
+ if (aSaveSettings)
{
AutoWriteLock vboxLock(this COMMA_LOCKVAL_SRC_POS);
rc = saveSettings();
vboxLock.release();
if (FAILED(rc))
- unregisterDHCPServer(aDHCPServer, false /* aSaveRegistry */);
+ unregisterDHCPServer(aDHCPServer, false /* aSaveSettings */);
}
return rc;
}
/**
- * Removes the given hard disk from the hard disk registry.
+ * Removes the given DHCP server from the settings.
*
- * @param aHardDisk Hard disk object to remove.
- * @param aSaveRegistry @c true to save hard disk registry to disk (default).
+ * @param aDHCPServer DHCP server object to remove.
+ * @param aSaveSettings @c true to save settings to disk (default).
*
- * When @a aSaveRegistry is @c true, this operation may fail because of the
- * failed #saveSettings() method it calls. In this case, the hard disk object
- * will NOT be removed from the registry when this method returns. It is
- * therefore the responsibility of the caller to call this method as the first
- * step of some action that requires unregistration, before calling uninit() on
- * @a aHardDisk.
+ * When @a aSaveSettings is @c true, this operation may fail because of the
+ * failed #saveSettings() method it calls. In this case, the DHCP server
+ * will NOT be removed from the settingsi when this method returns.
*
- * @note Locks this object for writing and @a aHardDisk for reading.
+ * @note Locks this object for writing.
*/
HRESULT VirtualBox::unregisterDHCPServer(DHCPServer *aDHCPServer,
- bool aSaveRegistry /*= true*/)
+ bool aSaveSettings /*= true*/)
{
AssertReturn(aDHCPServer != NULL, E_INVALIDARG);
@@ -4690,14 +5413,14 @@ HRESULT VirtualBox::unregisterDHCPServer(DHCPServer *aDHCPServer,
HRESULT rc = S_OK;
- if (aSaveRegistry)
+ if (aSaveSettings)
{
AutoWriteLock vboxLock(this COMMA_LOCKVAL_SRC_POS);
rc = saveSettings();
vboxLock.release();
if (FAILED(rc))
- registerDHCPServer(aDHCPServer, false /* aSaveRegistry */);
+ registerDHCPServer(aDHCPServer, false /* aSaveSettings */);
}
return rc;
diff --git a/src/VBox/Main/src-server/darwin/USBProxyServiceDarwin.cpp b/src/VBox/Main/src-server/darwin/USBProxyServiceDarwin.cpp
index 1ca09d69a..5ea0e93c8 100644
--- a/src/VBox/Main/src-server/darwin/USBProxyServiceDarwin.cpp
+++ b/src/VBox/Main/src-server/darwin/USBProxyServiceDarwin.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -38,8 +38,8 @@
/**
* Initialize data members.
*/
-USBProxyServiceDarwin::USBProxyServiceDarwin (Host *aHost)
- : USBProxyService (aHost), mServiceRunLoopRef (NULL), mNotifyOpaque (NULL), mWaitABitNextTime (false), mUSBLibInitialized (false)
+USBProxyServiceDarwin::USBProxyServiceDarwin(Host *aHost)
+ : USBProxyService(aHost), mServiceRunLoopRef(NULL), mNotifyOpaque(NULL), mWaitABitNextTime(false), mUSBLibInitialized(false)
{
LogFlowThisFunc(("aHost=%p\n", aHost));
}
@@ -100,15 +100,15 @@ USBProxyServiceDarwin::~USBProxyServiceDarwin()
#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
-void *USBProxyServiceDarwin::insertFilter (PCUSBFILTER aFilter)
+void *USBProxyServiceDarwin::insertFilter(PCUSBFILTER aFilter)
{
- return USBLibAddFilter (aFilter);
+ return USBLibAddFilter(aFilter);
}
-void USBProxyServiceDarwin::removeFilter (void *aId)
+void USBProxyServiceDarwin::removeFilter(void *aId)
{
- USBLibRemoveFilter (aId);
+ USBLibRemoveFilter(aId);
}
#endif /* VBOX_WITH_NEW_USB_CODE_ON_DARWIN */
@@ -119,8 +119,11 @@ int USBProxyServiceDarwin::captureDevice(HostUSBDevice *aDevice)
* Check preconditions.
*/
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
@@ -128,6 +131,7 @@ int USBProxyServiceDarwin::captureDevice(HostUSBDevice *aDevice)
* Fake it.
*/
ASMAtomicWriteBool(&mFakeAsync, true);
+ devLock.release();
interruptWait();
return VINF_SUCCESS;
@@ -160,6 +164,7 @@ int USBProxyServiceDarwin::captureDevice(HostUSBDevice *aDevice)
void USBProxyServiceDarwin::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
{
+ AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
/*
* Remove the one-shot filter if necessary.
@@ -178,8 +183,11 @@ int USBProxyServiceDarwin::releaseDevice(HostUSBDevice *aDevice)
* Check preconditions.
*/
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
@@ -187,6 +195,7 @@ int USBProxyServiceDarwin::releaseDevice(HostUSBDevice *aDevice)
* Fake it.
*/
ASMAtomicWriteBool(&mFakeAsync, true);
+ devLock.release();
interruptWait();
return VINF_SUCCESS;
@@ -221,6 +230,7 @@ int USBProxyServiceDarwin::releaseDevice(HostUSBDevice *aDevice)
void USBProxyServiceDarwin::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
{
+ AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
/*
* Remove the one-shot filter if necessary.
@@ -233,10 +243,11 @@ void USBProxyServiceDarwin::releaseDeviceCompleted(HostUSBDevice *aDevice, bool
}
+/** @todo unused */
void USBProxyServiceDarwin::detachingDevice(HostUSBDevice *aDevice)
{
#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
- aDevice->setLogicalReconnect (HostUSBDevice::kDetachingPendingDetach);
+ aDevice->setLogicalReconnect(HostUSBDevice::kDetachingPendingDetach);
#else
NOREF(aDevice);
#endif
@@ -245,6 +256,8 @@ void USBProxyServiceDarwin::detachingDevice(HostUSBDevice *aDevice)
bool USBProxyServiceDarwin::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
+ AssertReturn(aDevice, false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
/* We're faking async state stuff. */
return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
@@ -263,7 +276,7 @@ int USBProxyServiceDarwin::wait(RTMSINTERVAL aMillies)
return VINF_SUCCESS;
#endif
- SInt32 rc = CFRunLoopRunInMode(CFSTR (VBOX_IOKIT_MODE_STRING),
+ SInt32 rc = CFRunLoopRunInMode(CFSTR(VBOX_IOKIT_MODE_STRING),
mWaitABitNextTime && aMillies >= 1000
? 1.0 /* seconds */
: aMillies >= 5000 /* Temporary measure to poll for status changes (MSD). */
@@ -276,31 +289,31 @@ int USBProxyServiceDarwin::wait(RTMSINTERVAL aMillies)
}
-int USBProxyServiceDarwin::interruptWait (void)
+int USBProxyServiceDarwin::interruptWait(void)
{
if (mServiceRunLoopRef)
- CFRunLoopStop (mServiceRunLoopRef);
+ CFRunLoopStop(mServiceRunLoopRef);
return 0;
}
-PUSBDEVICE USBProxyServiceDarwin::getDevices (void)
+PUSBDEVICE USBProxyServiceDarwin::getDevices(void)
{
/* call iokit.cpp */
return DarwinGetUSBDevices();
}
-void USBProxyServiceDarwin::serviceThreadInit (void)
+void USBProxyServiceDarwin::serviceThreadInit(void)
{
mServiceRunLoopRef = CFRunLoopGetCurrent();
mNotifyOpaque = DarwinSubscribeUSBNotifications();
}
-void USBProxyServiceDarwin::serviceThreadTerm (void)
+void USBProxyServiceDarwin::serviceThreadTerm(void)
{
- DarwinUnsubscribeUSBNotifications (mNotifyOpaque);
+ DarwinUnsubscribeUSBNotifications(mNotifyOpaque);
mServiceRunLoopRef = NULL;
}
@@ -310,8 +323,8 @@ void USBProxyServiceDarwin::serviceThreadTerm (void)
*
* @param pCur The USB device to free.
*/
-void DarwinFreeUSBDeviceFromIOKit (PUSBDEVICE pCur)
+void DarwinFreeUSBDeviceFromIOKit(PUSBDEVICE pCur)
{
- USBProxyService::freeDevice (pCur);
+ USBProxyService::freeDevice(pCur);
}
diff --git a/src/VBox/Main/src-server/darwin/iokit.cpp b/src/VBox/Main/src-server/darwin/iokit.cpp
index 573d0809a..0045e7c0b 100644
--- a/src/VBox/Main/src-server/darwin/iokit.cpp
+++ b/src/VBox/Main/src-server/darwin/iokit.cpp
@@ -609,7 +609,7 @@ void *DarwinSubscribeUSBNotifications(void)
if (pNotify->NotifyRLSrc)
{
CFRunLoopRef RunLoopRef = CFRunLoopGetCurrent();
- CFRetain(RunLoopRef); /* Workaround for crash when cleaning up the TLS / runloop((sub)mode). See #2807. */
+ CFRetain(RunLoopRef); /* Workaround for crash when cleaning up the TLS / runloop((sub)mode). See @bugref{2807}. */
CFRunLoopAddSource(RunLoopRef, pNotify->NotifyRLSrc, CFSTR(VBOX_IOKIT_MODE_STRING));
/*
@@ -1682,7 +1682,7 @@ PDARWINETHERNIC DarwinGetEthernetControllers(void)
*/
int main(int argc, char **argv)
{
- RTR3Init();
+ RTR3InitExe(argc, &argv, 0);
if (1)
{
diff --git a/src/VBox/Main/src-server/freebsd/NetIf-freebsd.cpp b/src/VBox/Main/src-server/freebsd/NetIf-freebsd.cpp
index b3d45e979..7066dab96 100644
--- a/src/VBox/Main/src-server/freebsd/NetIf-freebsd.cpp
+++ b/src/VBox/Main/src-server/freebsd/NetIf-freebsd.cpp
@@ -268,7 +268,7 @@ int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list)
pNext += pIfAddrMsg->ifam_msglen;
}
- if (pSdl->sdl_type == IFT_ETHER)
+ if (pSdl->sdl_type == IFT_ETHER || pSdl->sdl_type == IFT_L2VLAN)
{
struct ifreq IfReq;
strcpy(IfReq.ifr_name, pNew->szShortName);
@@ -373,7 +373,7 @@ int NetIfGetConfigByName(PNETIFINFO pInfo)
pNext += pIfAddrMsg->ifam_msglen;
}
- if (!fSkip && pSdl->sdl_type == IFT_ETHER)
+ if (!fSkip && (pSdl->sdl_type == IFT_ETHER || pSdl->sdl_type == IFT_L2VLAN))
{
size_t cbNameLen = pSdl->sdl_nlen + 1;
memcpy(pInfo->MACAddress.au8, LLADDR(pSdl), sizeof(pInfo->MACAddress.au8));
diff --git a/src/VBox/Main/src-server/freebsd/USBProxyServiceFreeBSD.cpp b/src/VBox/Main/src-server/freebsd/USBProxyServiceFreeBSD.cpp
index 73607776e..ef8856a31 100644
--- a/src/VBox/Main/src-server/freebsd/USBProxyServiceFreeBSD.cpp
+++ b/src/VBox/Main/src-server/freebsd/USBProxyServiceFreeBSD.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -110,14 +110,17 @@ USBProxyServiceFreeBSD::~USBProxyServiceFreeBSD()
int USBProxyServiceFreeBSD::captureDevice(HostUSBDevice *aDevice)
{
- Log(("USBProxyServiceFreeBSD::captureDevice: %p {%s}\n", aDevice, aDevice->getName().c_str()));
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
/*
* Don't think we need to do anything when the device is held... fake it.
*/
Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
+ devLock.release();
interruptWait();
return VINF_SUCCESS;
@@ -126,14 +129,17 @@ int USBProxyServiceFreeBSD::captureDevice(HostUSBDevice *aDevice)
int USBProxyServiceFreeBSD::releaseDevice(HostUSBDevice *aDevice)
{
- Log(("USBProxyServiceFreeBSD::releaseDevice: %p\n", aDevice));
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
/*
* We're not really holding it atm., just fake it.
*/
Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
+ devLock.release();
interruptWait();
return VINF_SUCCESS;
@@ -142,12 +148,15 @@ int USBProxyServiceFreeBSD::releaseDevice(HostUSBDevice *aDevice)
bool USBProxyServiceFreeBSD::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
+ AssertReturn(aDevice, false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
+
return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
}
/**
- * A device was added, we need to adjust mUdevPolls.
+ * A device was added
*
* See USBProxyService::deviceAdded for details.
*/
diff --git a/src/VBox/Main/src-server/generic/AutostartDb-generic.cpp b/src/VBox/Main/src-server/generic/AutostartDb-generic.cpp
new file mode 100644
index 000000000..923e75fea
--- /dev/null
+++ b/src/VBox/Main/src-server/generic/AutostartDb-generic.cpp
@@ -0,0 +1,262 @@
+/* $Id: AutostartDb-generic.cpp $ */
+/** @file
+ * VirtualBox Main - Autostart implementation.
+ */
+
+/*
+ * Copyright (C) 2009-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <iprt/assert.h>
+#include <iprt/process.h>
+#include <iprt/path.h>
+#include <iprt/mem.h>
+#include <iprt/file.h>
+#include <iprt/string.h>
+
+#include "AutostartDb.h"
+
+#if defined(RT_OS_LINUX)
+/**
+ * Modifies the autostart database.
+ *
+ * @returns VBox status code.
+ * @param fAutostart Flag whether the autostart or autostop database is modified.
+ * @param fAddVM Flag whether a VM is added or removed from the database.
+ */
+int AutostartDb::autostartModifyDb(bool fAutostart, bool fAddVM)
+{
+ int rc = VINF_SUCCESS;
+ char *pszUser = NULL;
+
+ /* Check if the path is set. */
+ if (!m_pszAutostartDbPath)
+ return VERR_PATH_NOT_FOUND;
+
+ rc = RTProcQueryUsernameA(RTProcSelf(), &pszUser);
+ if (RT_SUCCESS(rc))
+ {
+ char *pszFile;
+ uint64_t fOpen = RTFILE_O_DENY_ALL | RTFILE_O_READWRITE;
+ RTFILE hAutostartFile;
+
+ AssertPtr(pszUser);
+
+ if (fAddVM)
+ fOpen |= RTFILE_O_OPEN_CREATE;
+ else
+ fOpen |= RTFILE_O_OPEN;
+
+ rc = RTStrAPrintf(&pszFile, "%s/%s.%s",
+ m_pszAutostartDbPath, pszUser, fAutostart ? "start" : "stop");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTFileOpen(&hAutostartFile, pszFile, fOpen);
+ if (RT_SUCCESS(rc))
+ {
+ uint64_t cbFile;
+
+ /*
+ * Files with more than 16 bytes are rejected because they just contain
+ * a number of the amount of VMs with autostart configured, so they
+ * should be really really small. Anything else is bogus.
+ */
+ rc = RTFileGetSize(hAutostartFile, &cbFile);
+ if ( RT_SUCCESS(rc)
+ && cbFile <= 16)
+ {
+ char abBuf[16 + 1]; /* trailing \0 */
+ uint32_t cAutostartVms = 0;
+
+ memset(abBuf, 0, sizeof(abBuf));
+
+ /* Check if the file was just created. */
+ if (cbFile)
+ {
+ rc = RTFileRead(hAutostartFile, abBuf, cbFile, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrToUInt32Ex(abBuf, NULL, 10 /* uBase */, &cAutostartVms);
+ if ( rc == VWRN_TRAILING_CHARS
+ || rc == VWRN_TRAILING_SPACES)
+ rc = VINF_SUCCESS;
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ size_t cbBuf;
+
+ /* Modify VM counter and write back. */
+ if (fAddVM)
+ cAutostartVms++;
+ else
+ cAutostartVms--;
+
+ if (cAutostartVms > 0)
+ {
+ cbBuf = RTStrPrintf(abBuf, sizeof(abBuf), "%u", cAutostartVms);
+ rc = RTFileSetSize(hAutostartFile, cbBuf);
+ if (RT_SUCCESS(rc))
+ rc = RTFileWriteAt(hAutostartFile, 0, abBuf, cbBuf, NULL);
+ }
+ else
+ {
+ /* Just delete the file if there are no VMs left. */
+ RTFileClose(hAutostartFile);
+ RTFileDelete(pszFile);
+ hAutostartFile = NIL_RTFILE;
+ }
+ }
+ }
+ else if (RT_SUCCESS(rc))
+ rc = VERR_FILE_TOO_BIG;
+
+ if (hAutostartFile != NIL_RTFILE)
+ RTFileClose(hAutostartFile);
+ }
+ RTStrFree(pszFile);
+ }
+
+ RTStrFree(pszUser);
+ }
+
+ return rc;
+}
+
+#endif
+
+AutostartDb::AutostartDb()
+{
+#ifdef RT_OS_LINUX
+ int rc = RTCritSectInit(&this->CritSect);
+ NOREF(rc);
+ m_pszAutostartDbPath = NULL;
+#endif
+}
+
+AutostartDb::~AutostartDb()
+{
+#ifdef RT_OS_LINUX
+ RTCritSectDelete(&this->CritSect);
+ if (m_pszAutostartDbPath)
+ RTStrFree(m_pszAutostartDbPath);
+#endif
+}
+
+int AutostartDb::setAutostartDbPath(const char *pszAutostartDbPathNew)
+{
+#if defined(RT_OS_LINUX)
+ char *pszAutostartDbPathTmp = NULL;
+
+ if (pszAutostartDbPathNew)
+ {
+ pszAutostartDbPathTmp = RTStrDup(pszAutostartDbPathNew);
+ if (!pszAutostartDbPathTmp)
+ return VERR_NO_MEMORY;
+ }
+
+ RTCritSectEnter(&this->CritSect);
+ if (m_pszAutostartDbPath)
+ RTStrFree(m_pszAutostartDbPath);
+
+ m_pszAutostartDbPath = pszAutostartDbPathTmp;
+ RTCritSectLeave(&this->CritSect);
+ return VINF_SUCCESS;
+#else
+ NOREF(pszAutostartDbPathNew);
+ return VERR_NOT_SUPPORTED;
+#endif
+}
+
+int AutostartDb::addAutostartVM(const char *pszVMId)
+{
+ int rc = VERR_NOT_SUPPORTED;
+
+#if defined(RT_OS_LINUX)
+ NOREF(pszVMId); /* Not needed */
+
+ RTCritSectEnter(&this->CritSect);
+ rc = autostartModifyDb(true /* fAutostart */, true /* fAddVM */);
+ RTCritSectLeave(&this->CritSect);
+#elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
+ NOREF(pszVMId); /* Not needed */
+ rc = VINF_SUCCESS;
+#else
+ NOREF(pszVMId);
+ rc = VERR_NOT_SUPPORTED;
+#endif
+
+ return rc;
+}
+
+int AutostartDb::removeAutostartVM(const char *pszVMId)
+{
+ int rc = VINF_SUCCESS;
+
+#if defined(RT_OS_LINUX)
+ NOREF(pszVMId); /* Not needed */
+ RTCritSectEnter(&this->CritSect);
+ rc = autostartModifyDb(true /* fAutostart */, false /* fAddVM */);
+ RTCritSectLeave(&this->CritSect);
+#elif defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
+ NOREF(pszVMId); /* Not needed */
+ rc = VINF_SUCCESS;
+#else
+ NOREF(pszVMId);
+ rc = VERR_NOT_SUPPORTED;
+#endif
+
+ return rc;
+}
+
+int AutostartDb::addAutostopVM(const char *pszVMId)
+{
+ int rc = VINF_SUCCESS;
+
+#if defined(RT_OS_LINUX)
+ NOREF(pszVMId); /* Not needed */
+ RTCritSectEnter(&this->CritSect);
+ rc = autostartModifyDb(false /* fAutostart */, true /* fAddVM */);
+ RTCritSectLeave(&this->CritSect);
+#elif defined(RT_OS_DARWIN)
+ NOREF(pszVMId); /* Not needed */
+ rc = VINF_SUCCESS;
+#else
+ NOREF(pszVMId);
+ rc = VERR_NOT_SUPPORTED;
+#endif
+
+ return rc;
+}
+
+int AutostartDb::removeAutostopVM(const char *pszVMId)
+{
+ int rc = VINF_SUCCESS;
+
+#if defined(RT_OS_LINUX)
+ NOREF(pszVMId); /* Not needed */
+ RTCritSectEnter(&this->CritSect);
+ rc = autostartModifyDb(false /* fAutostart */, false /* fAddVM */);
+ RTCritSectLeave(&this->CritSect);
+#elif defined(RT_OS_DARWIN)
+ NOREF(pszVMId); /* Not needed */
+ rc = VINF_SUCCESS;
+#else
+ NOREF(pszVMId);
+ rc = VERR_NOT_SUPPORTED;
+#endif
+
+ return rc;
+}
+
diff --git a/src/VBox/Main/src-server/generic/NetIf-generic.cpp b/src/VBox/Main/src-server/generic/NetIf-generic.cpp
index 0b16950c9..fdf72d6fc 100644
--- a/src/VBox/Main/src-server/generic/NetIf-generic.cpp
+++ b/src/VBox/Main/src-server/generic/NetIf-generic.cpp
@@ -78,6 +78,50 @@ static int NetIfAdpCtl(HostNetworkInterface * pIf, const char *pszAddr, const ch
return NetIfAdpCtl(strName.c_str(), pszAddr, pszOption, pszMask);
}
+int NetIfAdpCtlOut(const char * pcszName, const char * pcszCmd, char *pszBuffer, size_t cBufSize)
+{
+ char szAdpCtl[RTPATH_MAX];
+ int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " ") - strlen(pcszCmd));
+ if (RT_FAILURE(rc))
+ {
+ LogRel(("NetIfAdpCtlOut: Failed to get program path, rc=%Rrc\n", rc));
+ return VERR_INVALID_PARAMETER;
+ }
+ strcat(szAdpCtl, "/" VBOXNETADPCTL_NAME " ");
+ if (pcszName && strlen(pcszName) <= RTPATH_MAX - strlen(szAdpCtl) - 1 - strlen(pcszCmd))
+ {
+ strcat(szAdpCtl, pcszName);
+ strcat(szAdpCtl, " ");
+ strcat(szAdpCtl, pcszCmd);
+ }
+ else
+ {
+ LogRel(("NetIfAdpCtlOut: Command line is too long: %s%s %s\n", szAdpCtl, pcszName, pcszCmd));
+ return VERR_INVALID_PARAMETER;
+ }
+ if (strlen(szAdpCtl) < RTPATH_MAX - sizeof(" 2>&1"))
+ strcat(szAdpCtl, " 2>&1");
+ FILE *fp = popen(szAdpCtl, "r");
+ if (fp)
+ {
+ if (fgets(pszBuffer, cBufSize, fp))
+ {
+ if (!strncmp(VBOXNETADPCTL_NAME ":", pszBuffer, sizeof(VBOXNETADPCTL_NAME)))
+ {
+ LogRel(("NetIfAdpCtlOut: %s", pszBuffer));
+ rc = VERR_INTERNAL_ERROR;
+ }
+ }
+ else
+ {
+ LogRel(("NetIfAdpCtlOut: No output from " VBOXNETADPCTL_NAME));
+ rc = VERR_INTERNAL_ERROR;
+ }
+ pclose(fp);
+ }
+ return rc;
+}
+
int NetIfEnableStaticIpConfig(VirtualBox * /* vBox */, HostNetworkInterface * pIf, ULONG aOldIp, ULONG aNewIp, ULONG aMask)
{
const char *pszOption, *pszMask;
@@ -165,13 +209,24 @@ int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVBox,
}
else
strcat(szAdpCtl, "add");
+ if (strlen(szAdpCtl) < RTPATH_MAX - sizeof(" 2>&1"))
+ strcat(szAdpCtl, " 2>&1");
FILE *fp = popen(szAdpCtl, "r");
if (fp)
{
- char szBuf[VBOXNET_MAX_SHORT_NAME];
+ char szBuf[128]; /* We are not interested in long error messages. */
if (fgets(szBuf, sizeof(szBuf), fp))
{
+ if (!strncmp(VBOXNETADPCTL_NAME ":", szBuf, sizeof(VBOXNETADPCTL_NAME)))
+ {
+ progress->notifyComplete(E_FAIL,
+ COM_IIDOF(IHostNetworkInterface),
+ HostNetworkInterface::getStaticComponentName(),
+ "%s", szBuf);
+ pclose(fp);
+ return E_FAIL;
+ }
char *pLast = szBuf + strlen(szBuf) - 1;
if (pLast >= szBuf && *pLast == '\n')
*pLast = 0;
@@ -204,18 +259,30 @@ int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVBox,
}
RTMemFree(pInfo);
}
+ if ((rc = pclose(fp)) != 0)
+ {
+ progress->notifyComplete(E_FAIL,
+ COM_IIDOF(IHostNetworkInterface),
+ HostNetworkInterface::getStaticComponentName(),
+ "Failed to execute '"VBOXNETADPCTL_NAME " add' (exit status: %d)", rc);
+ rc = VERR_INTERNAL_ERROR;
+ }
}
- if ((rc = pclose(fp)) != 0)
+ else
{
+ /* Failed to add an interface */
+ rc = VERR_PERMISSION_DENIED;
progress->notifyComplete(E_FAIL,
COM_IIDOF(IHostNetworkInterface),
HostNetworkInterface::getStaticComponentName(),
- "Failed to execute '"VBOXNETADPCTL_NAME " add' (exit status: %d)", rc);
- rc = VERR_INTERNAL_ERROR;
+ "Failed to execute '"VBOXNETADPCTL_NAME " add' (exit status: %d). Check permissions!", rc);
+ pclose(fp);
}
}
if (RT_SUCCESS(rc))
progress->notifyComplete(rc);
+ else
+ hrc = E_FAIL;
}
}
@@ -225,6 +292,7 @@ int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVBox,
NOREF(pVBox);
NOREF(aHostNetworkInterface);
NOREF(aProgress);
+ NOREF(pcszName);
return VERR_NOT_IMPLEMENTED;
#endif
}
diff --git a/src/VBox/Main/src-server/linux/NetIf-linux.cpp b/src/VBox/Main/src-server/linux/NetIf-linux.cpp
index ebfd9e349..e6dbc3f97 100644
--- a/src/VBox/Main/src-server/linux/NetIf-linux.cpp
+++ b/src/VBox/Main/src-server/linux/NetIf-linux.cpp
@@ -148,6 +148,49 @@ static int getInterfaceInfo(int iSocket, const char *pszName, PNETIFINFO pInfo)
}
fclose(fp);
}
+ /*
+ * Don't even try to get speed for non-Ethernet interfaces, it only
+ * produces errors.
+ */
+ pInfo->uSpeedMbits = 0;
+ if (pInfo->enmMediumType == NETIF_T_ETHERNET)
+ {
+ /*
+ * I wish I could do simple ioctl here, but older kernels require root
+ * privileges for any ethtool commands.
+ */
+ char szBuf[256];
+ /* First, we try to retrieve the speed via sysfs. */
+ RTStrPrintf(szBuf, sizeof(szBuf), "/sys/class/net/%s/speed", pszName);
+ fp = fopen(szBuf, "r");
+ if (fp)
+ {
+ if (fscanf(fp, "%u", &pInfo->uSpeedMbits) != 1)
+ pInfo->uSpeedMbits = 0;
+ fclose(fp);
+ }
+ if (pInfo->uSpeedMbits == 10)
+ {
+ /* Check the cable is plugged in at all */
+ unsigned uCarrier = 0;
+ RTStrPrintf(szBuf, sizeof(szBuf), "/sys/class/net/%s/carrier", pszName);
+ fp = fopen(szBuf, "r");
+ if (fp)
+ {
+ if (fscanf(fp, "%u", &uCarrier) != 1 || uCarrier == 0)
+ pInfo->uSpeedMbits = 0;
+ fclose(fp);
+ }
+ }
+
+ if (pInfo->uSpeedMbits == 0)
+ {
+ /* Failed to get speed via sysfs, go to plan B. */
+ int rc = NetIfAdpCtlOut(pszName, "speed", szBuf, sizeof(szBuf));
+ if (RT_SUCCESS(rc))
+ pInfo->uSpeedMbits = RTStrToUInt32(szBuf);
+ }
+ }
}
return VINF_SUCCESS;
}
diff --git a/src/VBox/Main/src-server/linux/PerformanceLinux.cpp b/src/VBox/Main/src-server/linux/PerformanceLinux.cpp
index f5589995c..63116c149 100644
--- a/src/VBox/Main/src-server/linux/PerformanceLinux.cpp
+++ b/src/VBox/Main/src-server/linux/PerformanceLinux.cpp
@@ -18,10 +18,18 @@
*/
#include <stdio.h>
+#include <unistd.h>
+#include <sys/statvfs.h>
+#include <errno.h>
+#include <mntent.h>
#include <iprt/alloc.h>
+#include <iprt/cdefs.h>
+#include <iprt/ctype.h>
#include <iprt/err.h>
#include <iprt/param.h>
+#include <iprt/path.h>
#include <iprt/string.h>
+#include <iprt/mp.h>
#include <map>
#include <vector>
@@ -29,20 +37,32 @@
#include "Logging.h"
#include "Performance.h"
+#define VBOXVOLINFO_NAME "VBoxVolInfo"
+
namespace pm {
class CollectorLinux : public CollectorHAL
{
public:
+ CollectorLinux();
virtual int preCollect(const CollectorHints& hints, uint64_t /* iTick */);
virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
+ virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available);
+ virtual int getHostDiskSize(const char *name, uint64_t *size);
virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
+ virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx);
+ virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms);
virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
+
+ virtual int getDiskListByFs(const char *name, DiskList& list);
private:
- virtual int _getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
+ virtual int _getRawHostCpuLoad();
int getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed);
+ char *getDiskName(char *pszDiskName, size_t cbDiskName, const char *pszDevName, bool fTrimDigits);
+ void addVolumeDependencies(const char *pcszVolume, DiskList& listDisks);
+ char *trimTrailingDigits(char *pszName);
struct VMProcessStats
{
@@ -55,6 +75,8 @@ private:
VMProcessMap mProcessStats;
uint64_t mUser, mKernel, mIdle;
+ uint64_t mSingleUser, mSingleKernel, mSingleIdle;
+ uint32_t mHZ;
};
CollectorHAL *createHAL()
@@ -64,6 +86,19 @@ CollectorHAL *createHAL()
// Collector HAL for Linux
+CollectorLinux::CollectorLinux()
+{
+ long hz = sysconf(_SC_CLK_TCK);
+ if (hz == -1)
+ {
+ LogRel(("CollectorLinux failed to obtain HZ from kernel, assuming 100.\n"));
+ mHZ = 100;
+ }
+ else
+ mHZ = hz;
+ LogFlowThisFunc(("mHZ=%u\n", mHZ));
+}
+
int CollectorLinux::preCollect(const CollectorHints& hints, uint64_t /* iTick */)
{
std::vector<RTPROCESS> processes;
@@ -82,24 +117,52 @@ int CollectorLinux::preCollect(const CollectorHints& hints, uint64_t /* iTick */
}
if (hints.isHostCpuLoadCollected() || mProcessStats.size())
{
- _getRawHostCpuLoad(&mUser, &mKernel, &mIdle);
+ _getRawHostCpuLoad();
}
return VINF_SUCCESS;
}
-int CollectorLinux::_getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
+int CollectorLinux::_getRawHostCpuLoad()
{
int rc = VINF_SUCCESS;
- ULONG u32user, u32nice, u32kernel, u32idle;
+ long long unsigned uUser, uNice, uKernel, uIdle, uIowait, uIrq, uSoftirq;
FILE *f = fopen("/proc/stat", "r");
if (f)
{
- if (fscanf(f, "cpu %u %u %u %u", &u32user, &u32nice, &u32kernel, &u32idle) == 4)
+ char szBuf[128];
+ if (fgets(szBuf, sizeof(szBuf), f))
{
- *user = (uint64_t)u32user + u32nice;
- *kernel = u32kernel;
- *idle = u32idle;
+ if (sscanf(szBuf, "cpu %llu %llu %llu %llu %llu %llu %llu",
+ &uUser, &uNice, &uKernel, &uIdle, &uIowait,
+ &uIrq, &uSoftirq) == 7)
+ {
+ mUser = uUser + uNice;
+ mKernel = uKernel + uIrq + uSoftirq;
+ mIdle = uIdle + uIowait;
+ }
+ /* Try to get single CPU stats. */
+ if (fgets(szBuf, sizeof(szBuf), f))
+ {
+ if (sscanf(szBuf, "cpu0 %llu %llu %llu %llu %llu %llu %llu",
+ &uUser, &uNice, &uKernel, &uIdle, &uIowait,
+ &uIrq, &uSoftirq) == 7)
+ {
+ mSingleUser = uUser + uNice;
+ mSingleKernel = uKernel + uIrq + uSoftirq;
+ mSingleIdle = uIdle + uIowait;
+ }
+ else
+ {
+ /* Assume that this is not an SMP system. */
+ Assert(RTMpGetCount() == 1);
+ mSingleUser = mUser;
+ mSingleKernel = mKernel;
+ mSingleIdle = mIdle;
+ }
+ }
+ else
+ rc = VERR_FILE_IO_ERROR;
}
else
rc = VERR_FILE_IO_ERROR;
@@ -161,6 +224,49 @@ int CollectorLinux::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *availab
return rc;
}
+int CollectorLinux::getHostFilesystemUsage(const char *path, ULONG *total, ULONG *used, ULONG *available)
+{
+ struct statvfs stats;
+ const unsigned _MB = 1024 * 1024;
+
+ if (statvfs(path, &stats) == -1)
+ {
+ LogRel(("Failed to collect %s filesystem usage: errno=%d.\n", path, errno));
+ return VERR_ACCESS_DENIED;
+ }
+ uint64_t cbBlock = stats.f_frsize ? stats.f_frsize : stats.f_bsize;
+ *total = (ULONG)(cbBlock * stats.f_blocks / _MB);
+ *used = (ULONG)(cbBlock * (stats.f_blocks - stats.f_bfree) / _MB);
+ *available = (ULONG)(cbBlock * stats.f_bavail / _MB);
+
+ return VINF_SUCCESS;
+}
+
+int CollectorLinux::getHostDiskSize(const char *name, uint64_t *size)
+{
+ int rc = VINF_SUCCESS;
+ char *pszName = NULL;
+ long long unsigned int u64Size;
+
+ RTStrAPrintf(&pszName, "/sys/block/%s/size", name);
+ Assert(pszName);
+ FILE *f = fopen(pszName, "r");
+ RTMemFree(pszName);
+
+ if (f)
+ {
+ if (fscanf(f, "%llu", &u64Size) == 1)
+ *size = u64Size * 512;
+ else
+ rc = VERR_FILE_IO_ERROR;
+ fclose(f);
+ }
+ else
+ rc = VERR_ACCESS_DENIED;
+
+ return rc;
+}
+
int CollectorLinux::getProcessMemoryUsage(RTPROCESS process, ULONG *used)
{
VMProcessMap::const_iterator it = mProcessStats.find(process);
@@ -216,5 +322,193 @@ int CollectorLinux::getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uin
return rc;
}
+int CollectorLinux::getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx)
+{
+ int rc = VINF_SUCCESS;
+ char szIfName[/*IFNAMSIZ*/ 16 + 36];
+ long long unsigned int u64Rx, u64Tx;
+
+ RTStrPrintf(szIfName, sizeof(szIfName), "/sys/class/net/%s/statistics/rx_bytes", name);
+ FILE *f = fopen(szIfName, "r");
+ if (f)
+ {
+ if (fscanf(f, "%llu", &u64Rx) == 1)
+ *rx = u64Rx;
+ else
+ rc = VERR_FILE_IO_ERROR;
+ fclose(f);
+ RTStrPrintf(szIfName, sizeof(szIfName), "/sys/class/net/%s/statistics/tx_bytes", name);
+ f = fopen(szIfName, "r");
+ if (f)
+ {
+ if (fscanf(f, "%llu", &u64Tx) == 1)
+ *tx = u64Tx;
+ else
+ rc = VERR_FILE_IO_ERROR;
+ fclose(f);
+ }
+ else
+ rc = VERR_ACCESS_DENIED;
+ }
+ else
+ rc = VERR_ACCESS_DENIED;
+
+ return rc;
+}
+
+int CollectorLinux::getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms)
+{
+#if 0
+ int rc = VINF_SUCCESS;
+ char szIfName[/*IFNAMSIZ*/ 16 + 36];
+ long long unsigned int u64Busy, tmp;
+
+ RTStrPrintf(szIfName, sizeof(szIfName), "/sys/class/block/%s/stat", name);
+ FILE *f = fopen(szIfName, "r");
+ if (f)
+ {
+ if (fscanf(f, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
+ &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &u64Busy, &tmp) == 11)
+ {
+ *disk_ms = u64Busy;
+ *total_ms = (uint64_t)(mSingleUser + mSingleKernel + mSingleIdle) * 1000 / mHZ;
+ }
+ else
+ rc = VERR_FILE_IO_ERROR;
+ fclose(f);
+ }
+ else
+ rc = VERR_ACCESS_DENIED;
+#else
+ int rc = VERR_MISSING;
+ FILE *f = fopen("/proc/diskstats", "r");
+ if (f)
+ {
+ char szBuf[128];
+ while (fgets(szBuf, sizeof(szBuf), f))
+ {
+ char *pszBufName = szBuf;
+ while (*pszBufName == ' ') ++pszBufName; /* Skip spaces */
+ while (RT_C_IS_DIGIT(*pszBufName)) ++pszBufName; /* Skip major */
+ while (*pszBufName == ' ') ++pszBufName; /* Skip spaces */
+ while (RT_C_IS_DIGIT(*pszBufName)) ++pszBufName; /* Skip minor */
+ while (*pszBufName == ' ') ++pszBufName; /* Skip spaces */
+
+ char *pszBufData = strchr(pszBufName, ' ');
+ if (!pszBufData)
+ {
+ LogRel(("CollectorLinux::getRawHostDiskLoad() failed to parse disk stats: %s\n", szBuf));
+ continue;
+ }
+ *pszBufData++ = '\0';
+ if (!strcmp(name, pszBufName))
+ {
+ long long unsigned int u64Busy, tmp;
+
+ if (sscanf(pszBufData, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
+ &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &u64Busy, &tmp) == 11)
+ {
+ *disk_ms = u64Busy;
+ *total_ms = (uint64_t)(mSingleUser + mSingleKernel + mSingleIdle) * 1000 / mHZ;
+ rc = VINF_SUCCESS;
+ }
+ else
+ rc = VERR_FILE_IO_ERROR;
+ break;
+ }
+ }
+ fclose(f);
+ }
+#endif
+
+ return rc;
+}
+
+char *CollectorLinux::trimTrailingDigits(char *pszName)
+{
+ unsigned cbName = strlen(pszName);
+ if (cbName == 0)
+ return pszName;
+
+ char *pszEnd = pszName + cbName - 1;
+ while (pszEnd > pszName && (RT_C_IS_DIGIT(*pszEnd) || *pszEnd == '\n'))
+ pszEnd--;
+ pszEnd[1] = '\0';
+
+ return pszName;
+}
+
+char *CollectorLinux::getDiskName(char *pszDiskName, size_t cbDiskName, const char *pszDevName, bool fTrimDigits)
+{
+ unsigned cbName = 0;
+ unsigned cbDevName = strlen(pszDevName);
+ const char *pszEnd = pszDevName + cbDevName - 1;
+ if (fTrimDigits)
+ while (pszEnd > pszDevName && RT_C_IS_DIGIT(*pszEnd))
+ pszEnd--;
+ while (pszEnd > pszDevName && *pszEnd != '/')
+ {
+ cbName++;
+ pszEnd--;
+ }
+ RTStrCopy(pszDiskName, RT_MIN(cbName + 1, cbDiskName), pszEnd + 1);
+ return pszDiskName;
+}
+
+void CollectorLinux::addVolumeDependencies(const char *pcszVolume, DiskList& listDisks)
+{
+ char szVolInfo[RTPATH_MAX];
+ int rc = RTPathExecDir(szVolInfo, sizeof(szVolInfo) - sizeof("/" VBOXVOLINFO_NAME " ") - strlen(pcszVolume));
+ if (RT_FAILURE(rc))
+ {
+ LogRel(("VolInfo: Failed to get program path, rc=%Rrc\n", rc));
+ return;
+ }
+ strcat(szVolInfo, "/" VBOXVOLINFO_NAME " ");
+ strcat(szVolInfo, pcszVolume);
+
+ FILE *fp = popen(szVolInfo, "r");
+ if (fp)
+ {
+ char szBuf[128];
+
+ while (fgets(szBuf, sizeof(szBuf), fp))
+ listDisks.push_back(RTCString(trimTrailingDigits(szBuf)));
+
+ pclose(fp);
+ }
+ else
+ listDisks.push_back(RTCString(pcszVolume));
+}
+
+int CollectorLinux::getDiskListByFs(const char *pszPath, DiskList& listDisks)
+{
+ FILE *mtab = setmntent("/etc/mtab", "r");
+ if (mtab)
+ {
+ struct mntent *mntent;
+ while ((mntent = getmntent(mtab)))
+ {
+ if (strcmp(pszPath, mntent->mnt_dir) == 0)
+ {
+ char szDevName[128];
+ if (strncmp(mntent->mnt_fsname, "/dev/mapper", 11))
+ {
+ getDiskName(szDevName, sizeof(szDevName), mntent->mnt_fsname, true);
+ listDisks.push_back(RTCString(szDevName));
+ }
+ else
+ {
+ getDiskName(szDevName, sizeof(szDevName), mntent->mnt_fsname, false);
+ addVolumeDependencies(szDevName, listDisks);
+ }
+ break;
+ }
+ }
+ endmntent(mtab);
+ }
+ return VINF_SUCCESS;
+}
+
}
diff --git a/src/VBox/Main/src-server/linux/USBGetDevices.cpp b/src/VBox/Main/src-server/linux/USBGetDevices.cpp
index 1b8cf4d9c..d824a0178 100644
--- a/src/VBox/Main/src-server/linux/USBGetDevices.cpp
+++ b/src/VBox/Main/src-server/linux/USBGetDevices.cpp
@@ -873,7 +873,9 @@ static int addIfDevice(const char *pcszDevicesRoot,
unsigned bus = usbGetBusFromSysfsPath(pcszNode);
if (!bus)
return VINF_SUCCESS;
- unsigned device = RTLinuxSysFsReadIntFile(10, "%s/devnum", pcszNode);
+ int device = RTLinuxSysFsReadIntFile(10, "%s/devnum", pcszNode);
+ if (device < 0)
+ return VINF_SUCCESS;
dev_t devnum = usbMakeDevNum(bus, device);
if (!devnum)
return VINF_SUCCESS;
diff --git a/src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp b/src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp
index 79506554a..a89c3e006 100644
--- a/src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp
+++ b/src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -221,14 +221,17 @@ void USBProxyServiceLinux::doUsbfsCleanupAsNeeded()
int USBProxyServiceLinux::captureDevice(HostUSBDevice *aDevice)
{
- Log(("USBProxyServiceLinux::captureDevice: %p {%s}\n", aDevice, aDevice->getName().c_str()));
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
/*
* Don't think we need to do anything when the device is held... fake it.
*/
Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
+ devLock.release();
interruptWait();
return VINF_SUCCESS;
@@ -237,14 +240,17 @@ int USBProxyServiceLinux::captureDevice(HostUSBDevice *aDevice)
int USBProxyServiceLinux::releaseDevice(HostUSBDevice *aDevice)
{
- Log(("USBProxyServiceLinux::releaseDevice: %p\n", aDevice));
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
/*
* We're not really holding it atm., just fake it.
*/
Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
+ devLock.release();
interruptWait();
return VINF_SUCCESS;
@@ -253,10 +259,14 @@ int USBProxyServiceLinux::releaseDevice(HostUSBDevice *aDevice)
bool USBProxyServiceLinux::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
+ AssertReturn(aDevice, false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
if ( aUSBDevice->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE
&& aDevice->mUsb->enmState == USBDEVICESTATE_USED_BY_HOST)
LogRel(("USBProxy: Device %04x:%04x (%s) has become accessible.\n",
aUSBDevice->idVendor, aUSBDevice->idProduct, aUSBDevice->pszAddress));
+ devLock.release();
return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
}
@@ -268,6 +278,9 @@ bool USBProxyServiceLinux::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE
*/
void USBProxyServiceLinux::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice)
{
+ AssertReturnVoid(aDevice);
+ AssertReturnVoid(!aDevice->isWriteLockOnCurrentThread());
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
if (aUSBDevice->enmState == USBDEVICESTATE_USED_BY_HOST)
{
LogRel(("USBProxy: Device %04x:%04x (%s) isn't accessible. giving udev a few seconds to fix this...\n",
@@ -275,6 +288,7 @@ void USBProxyServiceLinux::deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, Sessio
mUdevPolls = 10; /* (10 * 500ms = 5s) */
}
+ devLock.release();
USBProxyService::deviceAdded(aDevice, llOpenedMachines, aUSBDevice);
}
@@ -348,6 +362,9 @@ int USBProxyServiceLinux::waitSysfs(RTMSINTERVAL aMillies)
int USBProxyServiceLinux::interruptWait(void)
{
+ AssertReturn(!isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
#ifdef VBOX_USB_WITH_SYSFS
LogFlowFunc(("mUsingUsbfsDevices=%d\n", mUsingUsbfsDevices));
if (!mUsingUsbfsDevices)
diff --git a/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp b/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp
index 34af0a088..d74f116bf 100644
--- a/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp
+++ b/src/VBox/Main/src-server/os2/USBProxyServiceOs2.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -37,31 +37,31 @@
/**
* Initialize data members.
*/
-USBProxyServiceOs2::USBProxyServiceOs2 (Host *aHost)
- : USBProxyService (aHost), mhev (NULLHANDLE), mhmod (NULLHANDLE),
- mpfnUsbRegisterChangeNotification (NULL), mpfnUsbDeregisterNotification (NULL),
- mpfnUsbQueryNumberDevices (NULL), mpfnUsbQueryDeviceReport (NULL)
+USBProxyServiceOs2::USBProxyServiceOs2(Host *aHost)
+ : USBProxyService(aHost), mhev(NULLHANDLE), mhmod(NULLHANDLE),
+ mpfnUsbRegisterChangeNotification(NULL), mpfnUsbDeregisterNotification(NULL),
+ mpfnUsbQueryNumberDevices(NULL), mpfnUsbQueryDeviceReport(NULL)
{
LogFlowThisFunc(("aHost=%p\n", aHost));
/*
* Try initialize the usbcalls stuff.
*/
- int rc = DosCreateEventSem (NULL, &mhev, 0, FALSE);
- rc = RTErrConvertFromOS2 (rc);
+ int rc = DosCreateEventSem(NULL, &mhev, 0, FALSE);
+ rc = RTErrConvertFromOS2(rc);
if (RT_SUCCESS(rc))
{
- rc = DosLoadModule (NULL, 0, (PCSZ)"usbcalls", &mhmod);
- rc = RTErrConvertFromOS2 (rc);
+ rc = DosLoadModule(NULL, 0, (PCSZ)"usbcalls", &mhmod);
+ rc = RTErrConvertFromOS2(rc);
if (RT_SUCCESS(rc))
{
- if ( (rc = DosQueryProcAddr (mhmod, 0, (PCSZ)"UsbQueryNumberDevices", (PPFN)&mpfnUsbQueryNumberDevices)) == NO_ERROR
- && (rc = DosQueryProcAddr (mhmod, 0, (PCSZ)"UsbQueryDeviceReport", (PPFN)&mpfnUsbQueryDeviceReport)) == NO_ERROR
- && (rc = DosQueryProcAddr (mhmod, 0, (PCSZ)"UsbRegisterChangeNotification", (PPFN)&mpfnUsbRegisterChangeNotification)) == NO_ERROR
- && (rc = DosQueryProcAddr (mhmod, 0, (PCSZ)"UsbDeregisterNotification", (PPFN)&mpfnUsbDeregisterNotification)) == NO_ERROR
+ if ( (rc = DosQueryProcAddr(mhmod, 0, (PCSZ)"UsbQueryNumberDevices", (PPFN)&mpfnUsbQueryNumberDevices)) == NO_ERROR
+ && (rc = DosQueryProcAddr(mhmod, 0, (PCSZ)"UsbQueryDeviceReport", (PPFN)&mpfnUsbQueryDeviceReport)) == NO_ERROR
+ && (rc = DosQueryProcAddr(mhmod, 0, (PCSZ)"UsbRegisterChangeNotification", (PPFN)&mpfnUsbRegisterChangeNotification)) == NO_ERROR
+ && (rc = DosQueryProcAddr(mhmod, 0, (PCSZ)"UsbDeregisterNotification", (PPFN)&mpfnUsbDeregisterNotification)) == NO_ERROR
)
{
- rc = mpfnUsbRegisterChangeNotification (&mNotifyId, mhev, mhev);
+ rc = mpfnUsbRegisterChangeNotification(&mNotifyId, mhev, mhev);
if (!rc)
{
/*
@@ -76,15 +76,15 @@ USBProxyServiceOs2::USBProxyServiceOs2 (Host *aHost)
}
}
- LogRel (("USBProxyServiceOs2: failed to register change notification, rc=%d\n", rc));
+ LogRel(("USBProxyServiceOs2: failed to register change notification, rc=%d\n", rc));
}
else
- LogRel (("USBProxyServiceOs2: failed to load usbcalls\n"));
+ LogRel(("USBProxyServiceOs2: failed to load usbcalls\n"));
- DosFreeModule (mhmod);
+ DosFreeModule(mhmod);
}
else
- LogRel (("USBProxyServiceOs2: failed to load usbcalls, rc=%d\n", rc));
+ LogRel(("USBProxyServiceOs2: failed to load usbcalls, rc=%d\n", rc));
mhmod = NULLHANDLE;
}
else
@@ -114,45 +114,51 @@ USBProxyServiceOs2::~USBProxyServiceOs2()
if (mhmod)
{
if (mpfnUsbDeregisterNotification)
- mpfnUsbDeregisterNotification (mNotifyId);
+ mpfnUsbDeregisterNotification(mNotifyId);
mpfnUsbRegisterChangeNotification = NULL;
mpfnUsbDeregisterNotification = NULL;
mpfnUsbQueryNumberDevices = NULL;
mpfnUsbQueryDeviceReport = NULL;
- DosFreeModule (mhmod);
+ DosFreeModule(mhmod);
mhmod = NULLHANDLE;
}
}
-int USBProxyServiceOs2::captureDevice (HostUSBDevice *aDevice)
+int USBProxyServiceOs2::captureDevice(HostUSBDevice *aDevice)
{
- Log (("USBProxyServiceOs2::captureDevice: %p\n", aDevice));
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
/*
* Don't think we need to do anything when the device is held... fake it.
*/
Assert(aDevice->isStatePending());
+ devLock.release();
interruptWait();
return VINF_SUCCESS;
}
-int USBProxyServiceOs2::releaseDevice (HostUSBDevice *aDevice)
+int USBProxyServiceOs2::releaseDevice(HostUSBDevice *aDevice)
{
- Log (("USBProxyServiceOs2::releaseDevice: %p\n", aDevice));
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
/*
* We're not really holding it atm., just fake it.
*/
Assert(aDevice->isStatePending());
+ devLock.release();
interruptWait();
return VINF_SUCCESS;
@@ -161,6 +167,8 @@ int USBProxyServiceOs2::releaseDevice (HostUSBDevice *aDevice)
bool USBProxyServiceOs2::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
+ AssertReturn(aDevice, false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
}
@@ -173,23 +181,23 @@ int USBProxyServiceOs2::wait(RTMSINTERVAL aMillies)
}
-int USBProxyServiceOs2::interruptWait (void)
+int USBProxyServiceOs2::interruptWait(void)
{
- int rc = DosPostEventSem (mhev);
+ int rc = DosPostEventSem(mhev);
return rc == NO_ERROR || rc == ERROR_ALREADY_POSTED
? VINF_SUCCESS
- : RTErrConvertFromOS2 (rc);
+ : RTErrConvertFromOS2(rc);
}
#include <stdio.h>
-PUSBDEVICE USBProxyServiceOs2::getDevices (void)
+PUSBDEVICE USBProxyServiceOs2::getDevices(void)
{
/*
* Count the devices.
*/
ULONG cDevices = 0;
- int rc = mpfnUsbQueryNumberDevices ((PULONG)&cDevices); /* Thanks to com/xpcom, PULONG and ULONG * aren't the same. */
+ int rc = mpfnUsbQueryNumberDevices((PULONG)&cDevices); /* Thanks to com/xpcom, PULONG and ULONG * aren't the same. */
if (rc)
return NULL;
diff --git a/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp b/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp
index 05fd34592..bc7008206 100644
--- a/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp
+++ b/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp
@@ -24,6 +24,7 @@
#include <iprt/err.h>
#include <iprt/ctype.h>
+#include <iprt/path.h>
#include <list>
#include "Logging.h"
@@ -46,9 +47,73 @@
#include <net/if_arp.h>
#include <net/if.h>
#include <sys/types.h>
+#include <kstat.h>
#include "DynLoadLibSolaris.h"
+static uint32_t getInstance(const char *pszIfaceName, char *pszDevName)
+{
+ /*
+ * Get the instance number from the interface name, then clip it off.
+ */
+ int cbInstance = 0;
+ int cbIface = strlen(pszIfaceName);
+ const char *pszEnd = pszIfaceName + cbIface - 1;
+ for (int i = 0; i < cbIface - 1; i++)
+ {
+ if (!RT_C_IS_DIGIT(*pszEnd))
+ break;
+ cbInstance++;
+ pszEnd--;
+ }
+
+ uint32_t uInstance = RTStrToUInt32(pszEnd + 1);
+ strncpy(pszDevName, pszIfaceName, cbIface - cbInstance);
+ pszDevName[cbIface - cbInstance] = '\0';
+ return uInstance;
+}
+
+static uint64_t kstatGet(const char *name)
+{
+ kstat_ctl_t *kc;
+ uint64_t uSpeed = 0;
+
+ if ((kc = kstat_open()) == 0)
+ {
+ LogRel(("kstat_open() -> %d\n", errno));
+ return 0;
+ }
+
+ kstat_t *ksAdapter = kstat_lookup(kc, "link", -1, (char *)name);
+ if (ksAdapter == 0)
+ {
+ char szModule[KSTAT_STRLEN];
+ uint32_t uInstance = getInstance(name, szModule);
+ ksAdapter = kstat_lookup(kc, szModule, uInstance, "phys");
+ if (ksAdapter == 0)
+ ksAdapter = kstat_lookup(kc, szModule, uInstance, name);
+ }
+ if (ksAdapter == 0)
+ LogRel(("Failed to get network statistics for %s\n", name));
+ else if (kstat_read(kc, ksAdapter, 0) == -1)
+ LogRel(("kstat_read(%s) -> %d\n", name, errno));
+ else
+ {
+ kstat_named_t *kn;
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"ifspeed")) == 0)
+ LogRel(("kstat_data_lookup(ifspeed) -> %d, name=%s\n", errno, name));
+ else
+ uSpeed = kn->value.ul;
+ }
+ kstat_close(kc);
+ return uSpeed;
+}
+
+static void queryIfaceSpeed(PNETIFINFO pInfo)
+{
+ pInfo->uSpeedMbits = kstatGet(pInfo->szShortName) / 1000000; /* bits -> Mbits */
+}
+
static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNetworkInterfaceList)
{
std::list<ComObjPtr<HostNetworkInterface> > *pList = (std::list<ComObjPtr<HostNetworkInterface> > *)pvHostNetworkInterfaceList;
@@ -81,10 +146,14 @@ static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNe
SolarisNICMap.insert(NICPair("igb", "Intel 82575 PCI-E Gigabit Ethernet"));
SolarisNICMap.insert(NICPair("ipge", "PCI-E Gigabit Ethernet"));
SolarisNICMap.insert(NICPair("iprb", "Intel 82557/58/59 Ethernet"));
+ SolarisNICMap.insert(NICPair("ixgb", "Intel 82597ex 10 Gigabit Ethernet"));
SolarisNICMap.insert(NICPair("ixgbe", "Intel 10 Gigabit PCI-E Ethernet"));
+ SolarisNICMap.insert(NICPair("mcxe", "Mellanox ConnectX-2 10 Gigabit Ethernet"));
SolarisNICMap.insert(NICPair("mxfe", "Macronix 98715 Fast Ethernet"));
SolarisNICMap.insert(NICPair("nfo", "Nvidia Gigabit Ethernet"));
SolarisNICMap.insert(NICPair("nge", "Nvidia Gigabit Ethernet"));
+ SolarisNICMap.insert(NICPair("ntxn", "NetXen 10/1 Gigabit Ethernet"));
+ SolarisNICMap.insert(NICPair("nxge", "Sun 10/1 Gigabit Ethernet"));
SolarisNICMap.insert(NICPair("pcelx", "3COM EtherLink III PCMCIA Ethernet"));
SolarisNICMap.insert(NICPair("pcn", "AMD PCnet Ethernet"));
SolarisNICMap.insert(NICPair("qfe", "SUNW,qfe Quad Fast-Ethernet"));
@@ -197,12 +266,14 @@ static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNe
Uuid.Gen.au8Node[5] = Info.MACAddress.au8[5];
Info.Uuid = Uuid;
Info.enmMediumType = NETIF_T_ETHERNET;
+ strncpy(Info.szShortName, szNICInstance, sizeof(Info.szShortName) - 1);
HostNetworkInterfaceType_T enmType;
if (strncmp("vboxnet", szNICInstance, 7))
enmType = HostNetworkInterfaceType_Bridged;
else
enmType = HostNetworkInterfaceType_HostOnly;
+ queryIfaceSpeed(&Info);
ComObjPtr<HostNetworkInterface> IfObj;
IfObj.createObject();
if (SUCCEEDED(IfObj->init(Bstr(szNICDesc), enmType, &Info)))
diff --git a/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp b/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp
index bcc1eae03..6b66393cc 100644
--- a/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp
+++ b/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp
@@ -23,32 +23,82 @@
#include <errno.h>
#include <fcntl.h>
#include <kstat.h>
+#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include <iprt/ctype.h>
#include <iprt/err.h>
#include <iprt/string.h>
#include <iprt/alloc.h>
#include <iprt/param.h>
-#include <VBox/log.h>
+#include <iprt/path.h>
+#include "Logging.h"
#include "Performance.h"
+#include <dlfcn.h>
+
+#include <libzfs.h>
+#include <libnvpair.h>
+
+#include <map>
+
namespace pm {
+ typedef libzfs_handle_t *(*PFNZFSINIT)(void);
+ typedef zfs_handle_t *(*PFNZFSOPEN)(libzfs_handle_t *, const char *, int);
+ typedef void (*PFNZFSCLOSE)(zfs_handle_t *);
+ typedef uint64_t (*PFNZFSPROPGETINT)(zfs_handle_t *, zfs_prop_t);
+ typedef zpool_handle_t *(*PFNZPOOLOPEN)(libzfs_handle_t *, const char *);
+ typedef void (*PFNZPOOLCLOSE)(zpool_handle_t *);
+ typedef nvlist_t *(*PFNZPOOLGETCONFIG)(zpool_handle_t *, nvlist_t **);
+ typedef char *(*PFNZPOOLVDEVNAME)(libzfs_handle_t *, zpool_handle_t *, nvlist_t *, boolean_t);
+
+ typedef std::map<RTCString,RTCString> FsMap;
+
class CollectorSolaris : public CollectorHAL
{
public:
CollectorSolaris();
virtual ~CollectorSolaris();
virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
+ virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available);
+ virtual int getHostDiskSize(const char *name, uint64_t *size);
virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
+ virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx);
+ virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms);
virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
+
+ virtual int getDiskListByFs(const char *name, DiskList& list);
private:
+ static uint32_t getInstance(const char *pszIfaceName, char *pszDevName);
+ uint64_t getZfsTotal(uint64_t cbTotal, const char *szFsType, const char *szFsName);
+ void updateFilesystemMap(void);
+ RTCString physToInstName(const char *pcszPhysName);
+ RTCString pathToInstName(const char *pcszDevPathName);
+ uint64_t wrapCorrection(uint32_t cur, uint64_t prev, const char *name);
+ uint64_t wrapDetection(uint64_t cur, uint64_t prev, const char *name);
+
kstat_ctl_t *mKC;
kstat_t *mSysPages;
kstat_t *mZFSCache;
+
+ void *mZfsSo;
+ libzfs_handle_t *mZfsLib;
+ PFNZFSINIT mZfsInit;
+ PFNZFSOPEN mZfsOpen;
+ PFNZFSCLOSE mZfsClose;
+ PFNZFSPROPGETINT mZfsPropGetInt;
+ PFNZPOOLOPEN mZpoolOpen;
+ PFNZPOOLCLOSE mZpoolClose;
+ PFNZPOOLGETCONFIG mZpoolGetConfig;
+ PFNZPOOLVDEVNAME mZpoolVdevName;
+
+ FsMap mFsMap;
};
CollectorHAL *createHAL()
@@ -62,7 +112,8 @@ CollectorHAL *createHAL()
CollectorSolaris::CollectorSolaris()
: mKC(0),
mSysPages(0),
- mZFSCache(0)
+ mZFSCache(0),
+ mZfsLib(0)
{
if ((mKC = kstat_open()) == 0)
{
@@ -70,22 +121,47 @@ CollectorSolaris::CollectorSolaris()
return;
}
- if ((mSysPages = kstat_lookup(mKC, "unix", 0, "system_pages")) == 0)
+ if ((mSysPages = kstat_lookup(mKC, (char *)"unix", 0, (char *)"system_pages")) == 0)
{
Log(("kstat_lookup(system_pages) -> %d\n", errno));
return;
}
- if ((mZFSCache = kstat_lookup(mKC, "zfs", 0, "arcstats")) == 0)
+ if ((mZFSCache = kstat_lookup(mKC, (char *)"zfs", 0, (char *)"arcstats")) == 0)
{
Log(("kstat_lookup(system_pages) -> %d\n", errno));
}
+
+ /* Try to load libzfs dynamically, it may be missing. */
+ mZfsSo = dlopen("libzfs.so", RTLD_LAZY);
+ if (mZfsSo)
+ {
+ mZfsInit = (PFNZFSINIT)dlsym(mZfsSo, "libzfs_init");
+ mZfsOpen = (PFNZFSOPEN)dlsym(mZfsSo, "zfs_open");
+ mZfsClose = (PFNZFSCLOSE)dlsym(mZfsSo, "zfs_close");
+ mZfsPropGetInt = (PFNZFSPROPGETINT)dlsym(mZfsSo, "zfs_prop_get_int");
+ mZpoolOpen = (PFNZPOOLOPEN)dlsym(mZfsSo, "zpool_open");
+ mZpoolClose = (PFNZPOOLCLOSE)dlsym(mZfsSo, "zpool_close");
+ mZpoolGetConfig = (PFNZPOOLGETCONFIG)dlsym(mZfsSo, "zpool_get_config");
+ mZpoolVdevName = (PFNZPOOLVDEVNAME)dlsym(mZfsSo, "zpool_vdev_name");
+
+ if (mZfsInit && mZfsOpen && mZfsClose && mZfsPropGetInt
+ && mZpoolOpen && mZpoolClose && mZpoolGetConfig && mZpoolVdevName)
+ mZfsLib = mZfsInit();
+ else
+ LogRel(("Incompatible libzfs? libzfs_init=%p zfs_open=%p zfs_close=%p zfs_prop_get_int=%p\n",
+ mZfsInit, mZfsOpen, mZfsClose, mZfsPropGetInt));
+ }
+
+ updateFilesystemMap();
}
CollectorSolaris::~CollectorSolaris()
{
if (mKC)
kstat_close(mKC);
+ if (mZfsSo)
+ dlclose(mZfsSo);
}
int CollectorSolaris::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
@@ -179,7 +255,7 @@ int CollectorSolaris::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *avail
Log(("kstat_read(sys_pages) -> %d\n", errno));
return VERR_INTERNAL_ERROR;
}
- if ((kn = (kstat_named_t *)kstat_data_lookup(mSysPages, "freemem")) == 0)
+ if ((kn = (kstat_named_t *)kstat_data_lookup(mSysPages, (char *)"freemem")) == 0)
{
Log(("kstat_data_lookup(freemem) -> %d\n", errno));
return VERR_INTERNAL_ERROR;
@@ -190,11 +266,11 @@ int CollectorSolaris::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *avail
{
if (mZFSCache)
{
- if ((kn = (kstat_named_t *)kstat_data_lookup(mZFSCache, "size")))
+ if ((kn = (kstat_named_t *)kstat_data_lookup(mZFSCache, (char *)"size")))
{
ulong_t ulSize = kn->value.ul;
- if ((kn = (kstat_named_t *)kstat_data_lookup(mZFSCache, "c_min")))
+ if ((kn = (kstat_named_t *)kstat_data_lookup(mZFSCache, (char *)"c_min")))
{
/*
* Account for ZFS minimum arc cache size limit.
@@ -214,7 +290,7 @@ int CollectorSolaris::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *avail
Log(("mZFSCache missing.\n"));
}
- if ((kn = (kstat_named_t *)kstat_data_lookup(mSysPages, "physmem")) == 0)
+ if ((kn = (kstat_named_t *)kstat_data_lookup(mSysPages, (char *)"physmem")) == 0)
{
Log(("kstat_data_lookup(physmem) -> %d\n", errno));
return VERR_INTERNAL_ERROR;
@@ -259,4 +335,392 @@ int CollectorSolaris::getProcessMemoryUsage(RTPROCESS process, ULONG *used)
return rc;
}
+uint32_t CollectorSolaris::getInstance(const char *pszIfaceName, char *pszDevName)
+{
+ /*
+ * Get the instance number from the interface name, then clip it off.
+ */
+ int cbInstance = 0;
+ int cbIface = strlen(pszIfaceName);
+ const char *pszEnd = pszIfaceName + cbIface - 1;
+ for (int i = 0; i < cbIface - 1; i++)
+ {
+ if (!RT_C_IS_DIGIT(*pszEnd))
+ break;
+ cbInstance++;
+ pszEnd--;
+ }
+
+ uint32_t uInstance = RTStrToUInt32(pszEnd + 1);
+ strncpy(pszDevName, pszIfaceName, cbIface - cbInstance);
+ pszDevName[cbIface - cbInstance] = '\0';
+ return uInstance;
+}
+
+uint64_t CollectorSolaris::wrapCorrection(uint32_t cur, uint64_t prev, const char *name)
+{
+ uint64_t corrected = (prev & 0xffffffff00000000) + cur;
+ if (cur < (prev & 0xffffffff))
+ {
+ /* wrap has occurred */
+ corrected += 0x100000000;
+ LogFlowThisFunc(("Corrected wrap on %s (%u < %u), returned %llu.\n",
+ name, cur, (uint32_t)prev, corrected));
+ }
+ return corrected;
+}
+
+uint64_t CollectorSolaris::wrapDetection(uint64_t cur, uint64_t prev, const char *name)
+{
+ static bool fNotSeen = true;
+
+ if (fNotSeen && cur < prev)
+ {
+ fNotSeen = false;
+ LogRel(("Detected wrap on %s (%llu < %llu).\n", name, cur, prev));
+ }
+ return cur;
+}
+
+/*
+ * WARNING! This function expects the previous values of rx and tx counter to
+ * be passed in as well as returnes new values in the same parameters. This is
+ * needed to provide a workaround for 32-bit counter wrapping.
+ */
+int CollectorSolaris::getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx)
+{
+ static bool g_fNotReported = true;
+ AssertReturn(strlen(name) < KSTAT_STRLEN, VERR_INVALID_PARAMETER);
+ LogFlowThisFunc(("m=%s i=%d n=%s\n", "link", -1, name));
+ kstat_t *ksAdapter = kstat_lookup(mKC, "link", -1, (char *)name);
+ if (ksAdapter == 0)
+ {
+ char szModule[KSTAT_STRLEN];
+ uint32_t uInstance = getInstance(name, szModule);
+ LogFlowThisFunc(("m=%s i=%u n=%s\n", szModule, uInstance, "phys"));
+ ksAdapter = kstat_lookup(mKC, szModule, uInstance, "phys");
+ if (ksAdapter == 0)
+ {
+ LogFlowThisFunc(("m=%s i=%u n=%s\n", szModule, uInstance, name));
+ ksAdapter = kstat_lookup(mKC, szModule, uInstance, (char *)name);
+ if (ksAdapter == 0)
+ {
+ LogRel(("Failed to get network statistics for %s\n", name));
+ return VERR_INTERNAL_ERROR;
+ }
+ }
+ }
+ if (kstat_read(mKC, ksAdapter, 0) == -1)
+ {
+ LogRel(("kstat_read(adapter) -> %d\n", errno));
+ return VERR_INTERNAL_ERROR;
+ }
+ kstat_named_t *kn;
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"rbytes64")) == 0)
+ {
+ if (g_fNotReported)
+ {
+ g_fNotReported = false;
+ LogRel(("Failed to locate rbytes64, falling back to 32-bit counters...\n"));
+ }
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"rbytes")) == 0)
+ {
+ LogRel(("kstat_data_lookup(rbytes) -> %d, name=%s\n", errno, name));
+ return VERR_INTERNAL_ERROR;
+ }
+ *rx = wrapCorrection(kn->value.ul, *rx, "rbytes");
+ }
+ else
+ *rx = wrapDetection(kn->value.ull, *rx, "rbytes64");
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"obytes64")) == 0)
+ {
+ if (g_fNotReported)
+ {
+ g_fNotReported = false;
+ LogRel(("Failed to locate obytes64, falling back to 32-bit counters...\n"));
+ }
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"obytes")) == 0)
+ {
+ LogRel(("kstat_data_lookup(obytes) -> %d\n", errno));
+ return VERR_INTERNAL_ERROR;
+ }
+ *tx = wrapCorrection(kn->value.ul, *tx, "obytes");
+ }
+ else
+ *tx = wrapDetection(kn->value.ull, *tx, "obytes64");
+ return VINF_SUCCESS;
+}
+
+int CollectorSolaris::getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms)
+{
+ int rc = VINF_SUCCESS;
+ AssertReturn(strlen(name) < KSTAT_STRLEN, VERR_INVALID_PARAMETER);
+ LogFlowThisFunc(("n=%s\n", name));
+ kstat_t *ksDisk = kstat_lookup(mKC, NULL, -1, (char *)name);
+ if (ksDisk != 0)
+ {
+ if (kstat_read(mKC, ksDisk, 0) == -1)
+ {
+ LogRel(("kstat_read(%s) -> %d\n", name, errno));
+ rc = VERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ kstat_io_t *ksIo = KSTAT_IO_PTR(ksDisk);
+ /*
+ * We do not care for wrap possibility here, although we may
+ * reconsider in about 300 years (9223372036854775807 ns).
+ */
+ *disk_ms = ksIo->rtime / 1000000;
+ *total_ms = ksDisk->ks_snaptime / 1000000;
+ }
+ }
+ else
+ {
+ LogRel(("kstat_lookup(%s) -> %d\n", name, errno));
+ rc = VERR_INTERNAL_ERROR;
+ }
+
+ return rc;
+}
+
+uint64_t CollectorSolaris::getZfsTotal(uint64_t cbTotal, const char *szFsType, const char *szFsName)
+{
+ if (strcmp(szFsType, "zfs"))
+ return cbTotal;
+ FsMap::iterator it = mFsMap.find(szFsName);
+ if (it == mFsMap.end())
+ return cbTotal;
+
+ char *pszDataset = strdup(it->second.c_str());
+ char *pszEnd = pszDataset + strlen(pszDataset);
+ uint64_t uAvail = 0;
+ while (pszEnd)
+ {
+ zfs_handle_t *hDataset;
+
+ *pszEnd = 0;
+ hDataset = mZfsOpen(mZfsLib, pszDataset, ZFS_TYPE_DATASET);
+ if (!hDataset)
+ break;
+
+ if (uAvail == 0)
+ {
+ uAvail = mZfsPropGetInt(hDataset, ZFS_PROP_REFQUOTA);
+ if (uAvail == 0)
+ uAvail = UINT64_MAX;
+ }
+
+ uint64_t uQuota = mZfsPropGetInt(hDataset, ZFS_PROP_QUOTA);
+ if (uQuota && uAvail > uQuota)
+ uAvail = uQuota;
+
+ pszEnd = strrchr(pszDataset, '/');
+ if (!pszEnd)
+ {
+ uint64_t uPoolSize = mZfsPropGetInt(hDataset, ZFS_PROP_USED) +
+ mZfsPropGetInt(hDataset, ZFS_PROP_AVAILABLE);
+ if (uAvail > uPoolSize)
+ uAvail = uPoolSize;
+ }
+ mZfsClose(hDataset);
+ }
+ free(pszDataset);
+
+ return uAvail ? uAvail : cbTotal;
+}
+
+int CollectorSolaris::getHostFilesystemUsage(const char *path, ULONG *total, ULONG *used, ULONG *available)
+{
+ struct statvfs64 stats;
+ const unsigned _MB = 1024 * 1024;
+
+ if (statvfs64(path, &stats) == -1)
+ {
+ LogRel(("Failed to collect %s filesystem usage: errno=%d.\n", path, errno));
+ return VERR_ACCESS_DENIED;
+ }
+ uint64_t cbBlock = stats.f_frsize ? stats.f_frsize : stats.f_bsize;
+ *total = (ULONG)(getZfsTotal(cbBlock * stats.f_blocks, stats.f_basetype, path) / _MB);
+ LogFlowThisFunc(("f_blocks=%llu.\n", stats.f_blocks));
+ *used = (ULONG)(cbBlock * (stats.f_blocks - stats.f_bfree) / _MB);
+ *available = (ULONG)(cbBlock * stats.f_bavail / _MB);
+
+ return VINF_SUCCESS;
+}
+
+int CollectorSolaris::getHostDiskSize(const char *name, uint64_t *size)
+{
+ int rc = VINF_SUCCESS;
+ AssertReturn(strlen(name) + 5 < KSTAT_STRLEN, VERR_INVALID_PARAMETER);
+ LogFlowThisFunc(("n=%s\n", name));
+ char szName[KSTAT_STRLEN];
+ strcpy(szName, name);
+ strcat(szName, ",err");
+ kstat_t *ksDisk = kstat_lookup(mKC, NULL, -1, szName);
+ if (ksDisk != 0)
+ {
+ if (kstat_read(mKC, ksDisk, 0) == -1)
+ {
+ LogRel(("kstat_read(%s) -> %d\n", name, errno));
+ rc = VERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ kstat_named_t *kn;
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksDisk, (char *)"Size")) == 0)
+ {
+ LogRel(("kstat_data_lookup(rbytes) -> %d, name=%s\n", errno, name));
+ return VERR_INTERNAL_ERROR;
+ }
+ *size = kn->value.ull;
+ }
+ }
+ else
+ {
+ LogRel(("kstat_lookup(%s) -> %d\n", szName, errno));
+ rc = VERR_INTERNAL_ERROR;
+ }
+
+
+ return rc;
+}
+
+RTCString CollectorSolaris::physToInstName(const char *pcszPhysName)
+{
+ FILE *fp = fopen("/etc/path_to_inst", "r");
+ if (!fp)
+ return RTCString();
+
+ RTCString strInstName;
+ size_t cbName = strlen(pcszPhysName);
+ char szBuf[RTPATH_MAX];
+ while (fgets(szBuf, sizeof(szBuf), fp))
+ {
+ if (szBuf[0] == '"' && strncmp(szBuf + 1, pcszPhysName, cbName) == 0)
+ {
+ char *pszDriver, *pszInstance;
+ pszDriver = strrchr(szBuf, '"');
+ if (pszDriver)
+ {
+ *pszDriver = '\0';
+ pszDriver = strrchr(szBuf, '"');
+ if (pszDriver)
+ {
+ *pszDriver++ = '\0';
+ pszInstance = strrchr(szBuf, ' ');
+ if (pszInstance)
+ {
+ *pszInstance = '\0';
+ pszInstance = strrchr(szBuf, ' ');
+ if (pszInstance)
+ {
+ *pszInstance++ = '\0';
+ strInstName = pszDriver;
+ strInstName += pszInstance;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ fclose(fp);
+
+ return strInstName;
+}
+
+RTCString CollectorSolaris::pathToInstName(const char *pcszDevPathName)
+{
+ char szLink[RTPATH_MAX];
+ if (readlink(pcszDevPathName, szLink, sizeof(szLink)) != -1)
+ {
+ char *pszStart, *pszEnd;
+ pszStart = strstr(szLink, "/devices/");
+ pszEnd = strrchr(szLink, ':');
+ if (pszStart && pszEnd)
+ {
+ pszStart += 8; // Skip "/devices"
+ *pszEnd = '\0'; // Trim partition
+ return physToInstName(pszStart);
+ }
+ }
+
+ return RTCString(pcszDevPathName);
+}
+
+int CollectorSolaris::getDiskListByFs(const char *name, DiskList& list)
+{
+ FsMap::iterator it = mFsMap.find(name);
+ if (it == mFsMap.end())
+ return VERR_INVALID_PARAMETER;
+
+ RTCString strName = it->second.substr(0, it->second.find("/"));
+ if (mZpoolOpen && mZpoolClose && mZpoolGetConfig && !strName.isEmpty())
+ {
+ zpool_handle_t *zh = mZpoolOpen(mZfsLib, strName.c_str());
+ if (zh)
+ {
+ unsigned int cChildren = 0;
+ nvlist_t **nvChildren = NULL;
+ nvlist_t *nvRoot = NULL;
+ nvlist_t *nvConfig = mZpoolGetConfig(zh, NULL);
+ if ( !nvlist_lookup_nvlist(nvConfig, ZPOOL_CONFIG_VDEV_TREE, &nvRoot)
+ && !nvlist_lookup_nvlist_array(nvRoot, ZPOOL_CONFIG_CHILDREN, &nvChildren, &cChildren))
+ {
+ for (unsigned int i = 0; i < cChildren; ++i)
+ {
+ uint64_t fHole = 0;
+ uint64_t fLog = 0;
+
+ nvlist_lookup_uint64(nvChildren[i], ZPOOL_CONFIG_IS_HOLE, &fHole);
+ nvlist_lookup_uint64(nvChildren[i], ZPOOL_CONFIG_IS_LOG, &fLog);
+
+ if (!fHole && !fLog)
+ {
+ char *pszChildName = mZpoolVdevName(mZfsLib, zh, nvChildren[i], _B_FALSE);
+ Assert(pszChildName);
+ RTCString strDevPath("/dev/dsk/");
+ strDevPath += pszChildName;
+ char szLink[RTPATH_MAX];
+ if (readlink(strDevPath.c_str(), szLink, sizeof(szLink)) != -1)
+ {
+ char *pszStart, *pszEnd;
+ pszStart = strstr(szLink, "/devices/");
+ pszEnd = strrchr(szLink, ':');
+ if (pszStart && pszEnd)
+ {
+ pszStart += 8; // Skip "/devices"
+ *pszEnd = '\0'; // Trim partition
+ list.push_back(physToInstName(pszStart));
+ }
+ }
+ free(pszChildName);
+ }
+ }
+ }
+ mZpoolClose(zh);
+ }
+ }
+ else
+ list.push_back(pathToInstName(it->second.c_str()));
+ return VINF_SUCCESS;
+}
+
+void CollectorSolaris::updateFilesystemMap(void)
+{
+ FILE *fp = fopen("/etc/mnttab", "r");
+ if (fp)
+ {
+ struct mnttab Entry;
+ int rc = 0;
+ resetmnttab(fp);
+ while ((rc = getmntent(fp, &Entry)) == 0)
+ mFsMap[Entry.mnt_mountp] = Entry.mnt_special;
+ fclose(fp);
+ if (rc != -1)
+ LogRel(("Error while reading mnttab: %d\n", rc));
+ }
+}
+
}
diff --git a/src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp b/src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp
index 6dc77de0a..8261d9904 100644
--- a/src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp
+++ b/src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -53,8 +53,8 @@ typedef USBDEVICELIST *PUSBDEVICELIST;
/**
* Initialize data members.
*/
-USBProxyServiceSolaris::USBProxyServiceSolaris (Host *aHost)
- : USBProxyService (aHost), mUSBLibInitialized(false)
+USBProxyServiceSolaris::USBProxyServiceSolaris(Host *aHost)
+ : USBProxyService(aHost), mUSBLibInitialized(false)
{
LogFlowThisFunc(("aHost=%p\n", aHost));
}
@@ -336,8 +336,11 @@ int USBProxyServiceSolaris::captureDevice(HostUSBDevice *aDevice)
* Check preconditions.
*/
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
AssertReturn(aDevice->mUsb, VERR_INVALID_POINTER);
@@ -371,6 +374,7 @@ int USBProxyServiceSolaris::captureDevice(HostUSBDevice *aDevice)
void USBProxyServiceSolaris::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
{
+ AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
/*
* Remove the one-shot filter if necessary.
*/
@@ -387,8 +391,11 @@ int USBProxyServiceSolaris::releaseDevice(HostUSBDevice *aDevice)
* Check preconditions.
*/
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
AssertReturn(aDevice->mUsb, VERR_INVALID_POINTER);
@@ -422,6 +429,7 @@ int USBProxyServiceSolaris::releaseDevice(HostUSBDevice *aDevice)
void USBProxyServiceSolaris::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
{
+ AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
/*
* Remove the one-shot filter if necessary.
*/
@@ -434,6 +442,8 @@ void USBProxyServiceSolaris::releaseDeviceCompleted(HostUSBDevice *aDevice, bool
bool USBProxyServiceSolaris::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
+ AssertReturn(aDevice, false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
}
diff --git a/src/VBox/Main/src-server/win/NetIf-win.cpp b/src/VBox/Main/src-server/win/NetIf-win.cpp
index 3377d585a..cce820da1 100644
--- a/src/VBox/Main/src-server/win/NetIf-win.cpp
+++ b/src/VBox/Main/src-server/win/NetIf-win.cpp
@@ -316,7 +316,7 @@ static HRESULT netIfNetworkInterfaceHelperClient(SVCHlpClient *aClient,
/* initialize the object returned to the caller by
* CreateHostOnlyNetworkInterface() */
- rc = d->iface->init(Bstr(name), guid, HostNetworkInterfaceType_HostOnly);
+ rc = d->iface->init(Bstr(name), Bstr(name), guid, HostNetworkInterfaceType_HostOnly);
if (SUCCEEDED(rc))
{
rc = d->iface->setVirtualBox(d->vBox);
diff --git a/src/VBox/Main/src-server/win/USBProxyServiceWindows.cpp b/src/VBox/Main/src-server/win/USBProxyServiceWindows.cpp
index f12cf37f3..8c8db31da 100644
--- a/src/VBox/Main/src-server/win/USBProxyServiceWindows.cpp
+++ b/src/VBox/Main/src-server/win/USBProxyServiceWindows.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2005-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -137,6 +137,17 @@ void USBProxyServiceWindows::removeFilter(void *aID)
int USBProxyServiceWindows::captureDevice(HostUSBDevice *aDevice)
{
/*
+ * Check preconditions.
+ */
+ AssertReturn(aDevice, VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
+
+ Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
+
+ /*
* Create a one-shot ignore filter for the device
* and trigger a re-enumeration of it.
*/
@@ -168,6 +179,17 @@ int USBProxyServiceWindows::captureDevice(HostUSBDevice *aDevice)
int USBProxyServiceWindows::releaseDevice(HostUSBDevice *aDevice)
{
/*
+ * Check preconditions.
+ */
+ AssertReturn(aDevice, VERR_GENERAL_FAILURE);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
+
+ AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
+ LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
+
+ Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
+
+ /*
* Create a one-shot ignore filter for the device
* and trigger a re-enumeration of it.
*/
@@ -199,13 +221,13 @@ int USBProxyServiceWindows::releaseDevice(HostUSBDevice *aDevice)
bool USBProxyServiceWindows::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
+ AssertReturn(aDevice, false);
+ AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
/* Nothing special here so far, so fall back on parent */
return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
/// @todo remove?
#if 0
- AssertReturn(aDevice, false);
- AssertReturn(aDevice->isWriteLockOnCurrentThread(), false);
/*
* We're only called in the 'existing device' state, so if there is a pending async
diff --git a/src/VBox/Main/src-server/win/svchlp.cpp b/src/VBox/Main/src-server/win/svchlp.cpp
index 2f749f53a..2191f3faa 100644
--- a/src/VBox/Main/src-server/win/svchlp.cpp
+++ b/src/VBox/Main/src-server/win/svchlp.cpp
@@ -1,6 +1,5 @@
/** @file
- *
- * Definition of SVC Helper Process control routines.
+ * Definition of SVC Helper Process control routines.
*/
/*
diff --git a/src/VBox/Main/src-server/win/svcmain.cpp b/src/VBox/Main/src-server/win/svcmain.cpp
index 4021cfabc..111c2dd43 100644
--- a/src/VBox/Main/src-server/win/svcmain.cpp
+++ b/src/VBox/Main/src-server/win/svcmain.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2004-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -37,6 +37,7 @@
#include <iprt/uni.h>
#include <iprt/path.h>
#include <iprt/getopt.h>
+#include <iprt/message.h>
#include <atlbase.h>
#include <atlcom.h>
@@ -158,7 +159,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpC
{
LPCTSTR lpCmdLine = GetCommandLine(); /* this line necessary for _ATL_MIN_CRT */
- /* Need to parse the command line before initializing the VBox runtime. */
+ /*
+ * Need to parse the command line before initializing the VBox runtime.
+ */
TCHAR szTokens[] = _T("-/");
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL)
@@ -187,7 +190,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpC
* Initialize the VBox runtime without loading
* the support driver.
*/
- RTR3Init();
+ int argc = __argc;
+ char **argv = __argv;
+ RTR3InitExe(argc, &argv, 0);
/* Note that all options are given lowercase/camel case/uppercase to
* approximate case insensitive matching, which RTGetOpt doesn't offer. */
@@ -232,7 +237,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpC
uint64_t uHistoryFileSize = 100 * _1M; // max 100MB per file
RTGETOPTSTATE GetOptState;
- int vrc = RTGetOptInit(&GetOptState, __argc, __argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
+ int vrc = RTGetOptInit(&GetOptState, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
AssertRC(vrc);
RTGETOPTUNION ValueUnion;
@@ -331,7 +336,15 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpC
if (RT_SUCCESS(vrc))
pszLogFile = RTStrDup(szLogFile);
}
- VBoxSVCLogRelCreate(pszLogFile, cHistory, uHistoryFileTime, uHistoryFileSize);
+ char szError[RTPATH_MAX + 128];
+ vrc = com::VBoxLogRelCreate("COM Server", pszLogFile,
+ RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG,
+ "all", "VBOXSVC_RELEASE_LOG",
+ RTLOGDEST_FILE, UINT32_MAX /* cMaxEntriesPerGroup */,
+ cHistory, uHistoryFileTime, uHistoryFileSize,
+ szError, sizeof(szError));
+ if (RT_FAILURE(vrc))
+ return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, vrc);
}
int nRet = 0;
diff --git a/src/VBox/Main/src-server/xpcom/server.cpp b/src/VBox/Main/src-server/xpcom/server.cpp
index b6773ead5..6c48fcba7 100644
--- a/src/VBox/Main/src-server/xpcom/server.cpp
+++ b/src/VBox/Main/src-server/xpcom/server.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2004-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -35,7 +35,6 @@
#include "Logging.h"
#include <VBox/param.h>
-#include <VBox/version.h>
#include <iprt/buildconfig.h>
#include <iprt/initterm.h>
@@ -225,14 +224,10 @@ NS_IMPL_THREADSAFE_ISUPPORTS1_CI(BandwidthControl, IBandwidthControl)
////////////////////////////////////////////////////////////////////////////////
-enum
-{
- /* Delay before shutting down the VirtualBox server after the last
- * VirtualBox instance is released, in ms */
- VBoxSVC_ShutdownDelay = 5000
-};
-
static bool gAutoShutdown = false;
+/** Delay before shutting down the VirtualBox server after the last
+ * VirtualBox instance is released, in ms */
+static uint32_t gShutdownDelayMs = 5000;
static nsIEventQueue *gEventQ = nsnull;
static PRBool volatile gKeepRunning = PR_TRUE;
@@ -343,14 +338,14 @@ public:
if (sTimer != NULL)
{
LogFlowFunc(("Last VirtualBox instance was released.\n"));
- LogFlowFunc(("Scheduling server shutdown in %d ms...\n",
- VBoxSVC_ShutdownDelay));
+ LogFlowFunc(("Scheduling server shutdown in %u ms...\n",
+ gShutdownDelayMs));
/* make sure the previous timer (if any) is stopped;
* otherwise RTTimerStart() will definitely fail. */
RTTimerLRStop(sTimer);
- int vrc = RTTimerLRStart(sTimer, uint64_t(VBoxSVC_ShutdownDelay) * 1000000);
+ int vrc = RTTimerLRStart(sTimer, gShutdownDelayMs * RT_NS_1MS_64);
AssertRC(vrc);
timerStarted = SUCCEEDED(vrc);
}
@@ -404,7 +399,7 @@ public:
/* called on the main thread */
void *handler()
{
- LogFlowFunc(("\n"));
+ LogFlowFuncEnter();
Assert(RTCritSectIsInitialized(&sLock));
@@ -431,6 +426,8 @@ public:
/* make it leave the event loop */
gKeepRunning = PR_FALSE;
}
+ else
+ LogFlowFunc(("No automatic shutdown.\n"));
}
else
{
@@ -442,6 +439,7 @@ public:
RTCritSectLeave(&sLock);
+ LogFlowFuncLeave();
return NULL;
}
};
@@ -788,14 +786,17 @@ int main(int argc, char **argv)
* Initialize the VBox runtime without loading
* the support driver
*/
- RTR3Init();
+ int vrc = RTR3InitExe(argc, &argv, 0);
+ if (RT_FAILURE(vrc))
+ return RTMsgInitFailure(vrc);
static const RTGETOPTDEF s_aOptions[] =
{
{ "--automate", 'a', RTGETOPT_REQ_NOTHING },
{ "--auto-shutdown", 'A', RTGETOPT_REQ_NOTHING },
{ "--daemonize", 'd', RTGETOPT_REQ_NOTHING },
- { "--pidfile", 'p', RTGETOPT_REQ_STRING },
+ { "--shutdown-delay", 'D', RTGETOPT_REQ_UINT32 },
+ { "--pidfile", 'p', RTGETOPT_REQ_STRING },
{ "--logfile", 'F', RTGETOPT_REQ_STRING },
{ "--logrotate", 'R', RTGETOPT_REQ_UINT32 },
{ "--logsize", 'S', RTGETOPT_REQ_UINT64 },
@@ -810,7 +811,7 @@ int main(int argc, char **argv)
PRFileDesc *daemon_pipe_wr = nsnull;
RTGETOPTSTATE GetOptState;
- int vrc = RTGetOptInit(&GetOptState, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
+ vrc = RTGetOptInit(&GetOptState, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
AssertRC(vrc);
RTGETOPTUNION ValueUnion;
@@ -819,33 +820,29 @@ int main(int argc, char **argv)
switch (vrc)
{
case 'a':
- {
/* --automate mode means we are started by XPCOM on
* demand. Daemonize ourselves and activate
* auto-shutdown. */
gAutoShutdown = true;
fDaemonize = true;
break;
- }
- /* --auto-shutdown mode means we're already daemonized. */
case 'A':
- {
+ /* --auto-shutdown mode means we're already daemonized. */
gAutoShutdown = true;
break;
- }
case 'd':
- {
fDaemonize = true;
break;
- }
+
+ case 'D':
+ gShutdownDelayMs = ValueUnion.u32;
+ break;
case 'p':
- {
g_pszPidFile = ValueUnion.psz;
break;
- }
case 'F':
pszLogFile = ValueUnion.psz;
@@ -864,16 +861,12 @@ int main(int argc, char **argv)
break;
case 'h':
- {
RTPrintf("no help\n");
return 1;
- }
case 'V':
- {
RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
return 0;
- }
default:
return RTGetOptPrintError(vrc, &ValueUnion);
@@ -901,7 +894,15 @@ int main(int argc, char **argv)
if (RT_FAILURE(vrc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to determine release log file (%Rrc)", vrc);
}
- VBoxSVCLogRelCreate(pszLogFile, cHistory, uHistoryFileTime, uHistoryFileSize);
+ char szError[RTPATH_MAX + 128];
+ vrc = com::VBoxLogRelCreate("XPCOM Server", pszLogFile,
+ RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG,
+ "all", "VBOXSVC_RELEASE_LOG",
+ RTLOGDEST_FILE, UINT32_MAX /* cMaxEntriesPerGroup */,
+ cHistory, uHistoryFileTime, uHistoryFileSize,
+ szError, sizeof(szError));
+ if (RT_FAILURE(vrc))
+ return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, vrc);
daemon_pipe_wr = PR_GetInheritedFD(VBOXSVC_STARTUP_PIPE_NAME);
RTEnvUnset("NSPR_INHERIT_FDS");
@@ -1010,7 +1011,7 @@ int main(int argc, char **argv)
for (int i = iSize; i > 0; i--)
putchar('*');
RTPrintf("\n%s\n", szBuf);
- RTPrintf("(C) 2008-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
+ RTPrintf("(C) 2004-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
"All rights reserved.\n");
#ifdef DEBUG
RTPrintf("Debug version.\n");
diff --git a/src/VBox/Main/testcase/Makefile.kmk b/src/VBox/Main/testcase/Makefile.kmk
index d35766846..a22746ea0 100644
--- a/src/VBox/Main/testcase/Makefile.kmk
+++ b/src/VBox/Main/testcase/Makefile.kmk
@@ -4,7 +4,7 @@
#
#
-# Copyright (C) 2006-2011 Oracle Corporation
+# Copyright (C) 2004-2012 Oracle Corporation
#
# This file is part of VirtualBox Open Source Edition (OSE), as
# available from http://www.virtualbox.org. This file is free software;
@@ -28,7 +28,8 @@ ifndef VBOX_ONLY_SDK
$(if $(VBOX_OSE),,tstOVF) \
$(if $(VBOX_WITH_XPCOM),tstVBoxAPILinux,tstVBoxAPIWin) \
$(if $(VBOX_WITH_RESOURCE_USAGE_API),tstCollector,) \
- $(if $(VBOX_WITH_GUEST_CONTROL),tstGuestCtrlParseBuffer,)
+ $(if $(VBOX_WITH_GUEST_CONTROL),tstGuestCtrlParseBuffer,) \
+ $(if $(VBOX_WITH_GUEST_CONTROL),tstGuestCtrlContextID,)
PROGRAMS.linux += \
$(if $(VBOX_WITH_USB),tstUSBProxyLinux,)
endif # !VBOX_WITH_TESTCASES
@@ -142,7 +143,7 @@ tstCollector_SOURCES = \
tstCollector_INCS = ../include
tstCollector_DEFS += VBOX_COLLECTOR_TEST_CASE
tstCollector_LDFLAGS.darwin += -lproc
-tstCollector_LDFLAGS.solaris += -lkstat
+tstCollector_LDFLAGS.solaris += -lkstat -lnvpair
tstCollector_LDFLAGS.win += psapi.lib powrprof.lib
@@ -150,9 +151,10 @@ tstCollector_LDFLAGS.win += psapi.lib powrprof.lib
# tstGuestCtrlParseBuffer
#
tstGuestCtrlParseBuffer_TEMPLATE = VBOXMAINCLIENTEXE
+tstGuestCtrlParseBuffer_DEFS += VBOX_WITH_HGCM VBOX_WITH_GUEST_CONTROL
tstGuestCtrlParseBuffer_SOURCES = \
tstGuestCtrlParseBuffer.cpp \
- ../src-client/GuestCtrlIO.cpp
+ ../src-client/GuestCtrlPrivate.cpp
tstGuestCtrlParseBuffer_INCS = ../include
ifeq ($(KBUILD_TARGET),win) ## @todo just add this to the template.
tstGuestCtrlParseBuffer_DEPS = $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h
@@ -162,6 +164,22 @@ endif
#
+# tstGuestCtrlContextID
+#
+tstGuestCtrlContextID_TEMPLATE = VBOXMAINCLIENTEXE
+tstGuestCtrlContextID_DEFS += VBOX_WITH_HGCM VBOX_WITH_GUEST_CONTROL
+tstGuestCtrlContextID_SOURCES = \
+ tstGuestCtrlContextID.cpp \
+ ../src-client/GuestCtrlPrivate.cpp
+tstGuestCtrlContextID_INCS = ../include
+ifeq ($(KBUILD_TARGET),win) ## @todo just add this to the template.
+ tstGuestCtrlContextID_DEPS = $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h
+else
+ tstGuestCtrlContextID_DEPS = $(VBOX_PATH_SDK)/bindings/xpcom/include/VirtualBox_XPCOM.h
+endif
+
+
+#
# tstUSBProxyLinux
#
tstUSBProxyLinux_TEMPLATE = VBOXR3TSTNPEXE
@@ -183,9 +201,10 @@ tstUSBProxyLinux_DEFS = \
tstUSBProxyLinux_DEPS = \
$(VBOX_PATH_SDK)/bindings/xpcom/include/VirtualBox_XPCOM.h
tstUSBProxyLinux_LIBS += \
- $(PATH_OUT)/lib/USBLib.a
+ $(PATH_OUT)/lib/USBLib.a \
+ $(PATH_OUT)/lib/VBoxCOM.a
# generate rules.
-include $(KBUILD_PATH)/subfooter.kmk
+include $(FILE_KBUILD_SUB_FOOTER)
diff --git a/src/VBox/Main/testcase/tstAPI.cpp b/src/VBox/Main/testcase/tstAPI.cpp
index f388ab272..978d0a25f 100644
--- a/src/VBox/Main/testcase/tstAPI.cpp
+++ b/src/VBox/Main/testcase/tstAPI.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -200,7 +200,7 @@ int main(int argc, char *argv[])
* Initialize the VBox runtime without loading
* the support driver.
*/
- RTR3Init();
+ RTR3InitExe(argc, &argv, 0);
HRESULT rc;
@@ -1185,25 +1185,25 @@ int main(int argc, char *argv[])
ComPtr<IHostNetworkInterface> networkInterface = hostNetworkInterfaces[0];
Bstr interfaceName;
networkInterface->COMGETTER(Name)(interfaceName.asOutParam());
- RTPrintf("Found %d network interfaces, testing with %lS...\n", hostNetworkInterfaces.size(), interfaceName.raw());
- Guid interfaceGuid;
+ RTPrintf("Found %d network interfaces, testing with %ls...\n", hostNetworkInterfaces.size(), interfaceName.raw());
+ Bstr interfaceGuid;
networkInterface->COMGETTER(Id)(interfaceGuid.asOutParam());
// Find the interface by its name
networkInterface.setNull();
CHECK_ERROR_BREAK(host,
- FindHostNetworkInterfaceByName(interfaceName, networkInterface.asOutParam()));
- Guid interfaceGuid2;
+ FindHostNetworkInterfaceByName(interfaceName.raw(), networkInterface.asOutParam()));
+ Bstr interfaceGuid2;
networkInterface->COMGETTER(Id)(interfaceGuid2.asOutParam());
if (interfaceGuid2 != interfaceGuid)
- RTPrintf("Failed to retrieve an interface by name %lS.\n", interfaceName.raw());
+ RTPrintf("Failed to retrieve an interface by name %ls.\n", interfaceName.raw());
// Find the interface by its guid
networkInterface.setNull();
CHECK_ERROR_BREAK(host,
- FindHostNetworkInterfaceById(interfaceGuid, networkInterface.asOutParam()));
+ FindHostNetworkInterfaceById(interfaceGuid.raw(), networkInterface.asOutParam()));
Bstr interfaceName2;
networkInterface->COMGETTER(Name)(interfaceName2.asOutParam());
if (interfaceName != interfaceName2)
- RTPrintf("Failed to retrieve an interface by GUID %lS.\n", Bstr(interfaceGuid.toString()).raw());
+ RTPrintf("Failed to retrieve an interface by GUID %ls.\n", interfaceGuid.raw());
}
else
{
@@ -1221,6 +1221,47 @@ int main(int argc, char *argv[])
// Fill base metrics array
+ Bstr baseMetricNames[] = { L"Net/eth0/Load" };
+ com::SafeArray<BSTR> baseMetrics(1);
+ baseMetricNames[0].cloneTo(&baseMetrics[0]);
+
+ // Get host
+ ComPtr<IHost> host;
+ CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));
+
+ // Get host network interfaces
+ // com::SafeIfaceArray<IHostNetworkInterface> hostNetworkInterfaces;
+ // CHECK_ERROR_BREAK(host,
+ // COMGETTER(NetworkInterfaces)(ComSafeArrayAsOutParam(hostNetworkInterfaces)));
+
+ // Setup base metrics
+ // Note that one needs to set up metrics after a session is open for a machine.
+ com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;
+ com::SafeIfaceArray<IUnknown> objects(1);
+ host.queryInterfaceTo(&objects[0]);
+ CHECK_ERROR_BREAK(collector, SetupMetrics(ComSafeArrayAsInParam(baseMetrics),
+ ComSafeArrayAsInParam(objects), 1u, 10u,
+ ComSafeArrayAsOutParam(affectedMetrics)));
+ listAffectedMetrics(virtualBox,
+ ComSafeArrayAsInParam(affectedMetrics));
+ affectedMetrics.setNull();
+
+ RTPrintf("Sleeping for 5 seconds...\n");
+ RTThreadSleep(5000); // Sleep for 5 seconds
+
+ RTPrintf("\nMetrics collected: --------------------\n");
+ queryMetrics(virtualBox, collector, ComSafeArrayAsInParam(objects));
+ } while (false);
+#endif /* VBOX_WITH_RESOURCE_USAGE_API */
+#if 0 && defined(VBOX_WITH_RESOURCE_USAGE_API)
+ do {
+ // Get collector
+ ComPtr<IPerformanceCollector> collector;
+ CHECK_ERROR_BREAK(virtualBox,
+ COMGETTER(PerformanceCollector)(collector.asOutParam()));
+
+
+ // Fill base metrics array
//Bstr baseMetricNames[] = { L"CPU/Load,RAM/Usage" };
Bstr baseMetricNames[] = { L"RAM/VMM" };
com::SafeArray<BSTR> baseMetrics(1);
@@ -1413,10 +1454,11 @@ int main(int argc, char *argv[])
{
com::ProgressErrorInfo info(progress);
if (info.isBasicAvailable())
- RTPrintf("Error: failed to import appliance. Error message: %lS\n", info.getText().raw());
+ RTPrintf("Error: failed to import appliance. Error message: %ls\n", info.getText().raw());
else
RTPrintf("Error: failed to import appliance. No error message available!\n");
- }else
+ }
+ else
RTPrintf("Successfully imported the appliance.\n");
}
@@ -1424,6 +1466,90 @@ int main(int argc, char *argv[])
while (FALSE);
RTPrintf("\n");
#endif
+#if 0
+ // check of network bandwidth control
+ ///////////////////////////////////////////////////////////////////////////
+ do
+ {
+ Bstr name = argc > 1 ? argv[1] : "ubuntu";
+ Bstr sessionType = argc > 2 ? argv[2] : "headless";
+ Bstr grpName = "tstAPI";
+ {
+ // Get machine
+ ComPtr<IMachine> machine;
+ ComPtr<IBandwidthControl> bwCtrl;
+ ComPtr<IBandwidthGroup> bwGroup;
+ ComPtr<INetworkAdapter> nic;
+ RTPrintf("Getting a machine object named '%ls'...\n", name.raw());
+ CHECK_ERROR_BREAK(virtualBox, FindMachine(name.raw(), machine.asOutParam()));
+ /* open a session for the VM (new or shared) */
+ CHECK_ERROR_BREAK(machine, LockMachine(session, LockType_Shared));
+ SessionType_T st;
+ CHECK_ERROR_BREAK(session, COMGETTER(Type)(&st));
+ bool fRunTime = (st == SessionType_Shared);
+ if (fRunTime)
+ {
+ RTPrintf("Machine %ls must not be running!\n");
+ break;
+ }
+ /* get the mutable session machine */
+ session->COMGETTER(Machine)(machine.asOutParam());
+ CHECK_ERROR_BREAK(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()));
+
+ RTPrintf("Creating bandwidth group named '%ls'...\n", grpName.raw());
+ CHECK_ERROR_BREAK(bwCtrl, CreateBandwidthGroup(grpName.raw(), BandwidthGroupType_Network, 123));
+
+
+ CHECK_ERROR_BREAK(bwCtrl, GetBandwidthGroup(grpName.raw(), bwGroup.asOutParam()));
+ CHECK_ERROR_BREAK(machine, GetNetworkAdapter(0, nic.asOutParam()));
+ RTPrintf("Assigning the group to the first network adapter...\n");
+ CHECK_ERROR_BREAK(nic, COMSETTER(BandwidthGroup)(bwGroup));
+ CHECK_ERROR_BREAK(machine, SaveSettings());
+ RTPrintf("Press enter to close this session...");
+ getchar();
+ session->UnlockMachine();
+ }
+ {
+ // Get machine
+ ComPtr<IMachine> machine;
+ ComPtr<IBandwidthControl> bwCtrl;
+ ComPtr<IBandwidthGroup> bwGroup;
+ Bstr grpNameReadFromNic;
+ ComPtr<INetworkAdapter> nic;
+ RTPrintf("Getting a machine object named '%ls'...\n", name.raw());
+ CHECK_ERROR_BREAK(virtualBox, FindMachine(name.raw(), machine.asOutParam()));
+ /* open a session for the VM (new or shared) */
+ CHECK_ERROR_BREAK(machine, LockMachine(session, LockType_Shared));
+ /* get the mutable session machine */
+ session->COMGETTER(Machine)(machine.asOutParam());
+ CHECK_ERROR_BREAK(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()));
+ CHECK_ERROR_BREAK(machine, GetNetworkAdapter(0, nic.asOutParam()));
+
+ RTPrintf("Reading the group back from the first network adapter...\n");
+ CHECK_ERROR_BREAK(nic, COMGETTER(BandwidthGroup)(bwGroup.asOutParam()));
+ if (bwGroup.isNull())
+ RTPrintf("Error: Bandwidth group is null at the first network adapter!\n");
+ else
+ {
+ CHECK_ERROR_BREAK(bwGroup, COMGETTER(Name)(grpNameReadFromNic.asOutParam()));
+ if (grpName != grpNameReadFromNic)
+ RTPrintf("Error: Bandwidth group names do not match (%ls != %ls)!\n", grpName.raw(), grpNameReadFromNic.raw());
+ else
+ RTPrintf("Successfully retrieved bandwidth group attribute from NIC (name=%ls)\n", grpNameReadFromNic.raw());
+ ComPtr<IBandwidthGroup> bwGroupEmpty;
+ RTPrintf("Assigning an empty group to the first network adapter...\n");
+ CHECK_ERROR_BREAK(nic, COMSETTER(BandwidthGroup)(bwGroupEmpty));
+ }
+ RTPrintf("Removing bandwidth group named '%ls'...\n", grpName.raw());
+ CHECK_ERROR_BREAK(bwCtrl, DeleteBandwidthGroup(grpName.raw()));
+ CHECK_ERROR_BREAK(machine, SaveSettings());
+ RTPrintf("Press enter to close this session...");
+ getchar();
+ session->UnlockMachine();
+ }
+ } while (FALSE);
+ RTPrintf("\n");
+#endif
RTPrintf("Press enter to release Session and VirtualBox instances...");
getchar();
diff --git a/src/VBox/Main/testcase/tstCollector.cpp b/src/VBox/Main/testcase/tstCollector.cpp
index 32e52ccdc..81525ec9e 100644
--- a/src/VBox/Main/testcase/tstCollector.cpp
+++ b/src/VBox/Main/testcase/tstCollector.cpp
@@ -141,16 +141,161 @@ void measurePerformance(pm::CollectorHAL *collector, const char *pszName, int cV
std::for_each(processes.begin(), processes.end(), std::ptr_fun(RTProcTerminate));
}
+#ifdef RT_OS_SOLARIS
+#define NETIFNAME "net0"
+#else
+#define NETIFNAME "eth0"
+#endif
+int testNetwork(pm::CollectorHAL *collector)
+{
+ pm::CollectorHints hints;
+ uint64_t hostRxStart, hostTxStart;
+ uint64_t hostRxStop, hostTxStop, speed = 125000000; /* Assume 1Gbit/s */
+
+ RTPrintf("tstCollector: TESTING - Network load, sleeping for 5 sec...\n");
+
+ hostRxStart = hostTxStart = 0;
+ int rc = collector->preCollect(hints, 0);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: preCollect() -> %Rrc\n", rc);
+ return 1;
+ }
+ rc = collector->getRawHostNetworkLoad(NETIFNAME, &hostRxStart, &hostTxStart);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: getRawHostNetworkLoad() -> %Rrc\n", rc);
+ return 1;
+ }
+
+ RTThreadSleep(5000); // Sleep for five seconds
+
+ rc = collector->preCollect(hints, 0);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: preCollect() -> %Rrc\n", rc);
+ return 1;
+ }
+ hostRxStop = hostRxStart;
+ hostTxStop = hostTxStart;
+ rc = collector->getRawHostNetworkLoad(NETIFNAME, &hostRxStop, &hostTxStop);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: getRawHostNetworkLoad() -> %Rrc\n", rc);
+ return 1;
+ }
+ RTPrintf("tstCollector: host network speed = %llu bytes/sec (%llu mbit/sec)\n",
+ speed, speed/(1000000/8));
+ RTPrintf("tstCollector: host network rx = %llu bytes/sec (%llu mbit/sec, %u.%u %%)\n",
+ (hostRxStop - hostRxStart)/5, (hostRxStop - hostRxStart)/(5000000/8),
+ (hostRxStop - hostRxStart) * 100 / (speed * 5),
+ (hostRxStop - hostRxStart) * 10000 / (speed * 5) % 100);
+ RTPrintf("tstCollector: host network tx = %llu bytes/sec (%llu mbit/sec, %u.%u %%)\n\n",
+ (hostTxStop - hostTxStart)/5, (hostTxStop - hostTxStart)/(5000000/8),
+ (hostTxStop - hostTxStart) * 100 / (speed * 5),
+ (hostTxStop - hostTxStart) * 10000 / (speed * 5) % 100);
+
+ return 0;
+}
+
+#define FSNAME "/"
+int testFsUsage(pm::CollectorHAL *collector)
+{
+ RTPrintf("tstCollector: TESTING - File system usage\n");
+
+ ULONG total, used, available;
+
+ int rc = collector->getHostFilesystemUsage(FSNAME, &total, &used, &available);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: getHostFilesystemUsage() -> %Rrc\n", rc);
+ return 1;
+ }
+ RTPrintf("tstCollector: host root fs total = %lu mB\n", total);
+ RTPrintf("tstCollector: host root fs used = %lu mB\n", used);
+ RTPrintf("tstCollector: host root fs available = %lu mB\n\n", available);
+ return 0;
+}
+
+int testDisk(pm::CollectorHAL *collector)
+{
+ pm::CollectorHints hints;
+ uint64_t diskMsStart, totalMsStart;
+ uint64_t diskMsStop, totalMsStop;
+
+ std::list<RTCString> disks;
+ int rc = collector->getDiskListByFs(FSNAME, disks);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: getDiskListByFs(%s) -> %Rrc\n", FSNAME, rc);
+ return 1;
+ }
+ if (disks.empty())
+ {
+ RTPrintf("tstCollector: getDiskListByFs(%s) returned empty list\n", FSNAME);
+ return 1;
+ }
+
+ uint64_t diskSize = 0;
+ rc = collector->getHostDiskSize(disks.front().c_str(), &diskSize);
+ RTPrintf("tstCollector: TESTING - Disk size (%s) = %llu\n", disks.front().c_str(), diskSize);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: getHostDiskSize() -> %Rrc\n", rc);
+ return 1;
+ }
+
+ RTPrintf("tstCollector: TESTING - Disk utilization (%s), sleeping for 5 sec...\n", disks.front().c_str());
+
+ hints.collectHostCpuLoad();
+ rc = collector->preCollect(hints, 0);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: preCollect() -> %Rrc\n", rc);
+ return 1;
+ }
+ rc = collector->getRawHostDiskLoad(disks.front().c_str(), &diskMsStart, &totalMsStart);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: getRawHostDiskLoad() -> %Rrc\n", rc);
+ return 1;
+ }
+
+ RTThreadSleep(5000); // Sleep for five seconds
+
+ rc = collector->preCollect(hints, 0);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: preCollect() -> %Rrc\n", rc);
+ return 1;
+ }
+ rc = collector->getRawHostDiskLoad(disks.front().c_str(), &diskMsStop, &totalMsStop);
+ if (RT_FAILURE(rc))
+ {
+ RTPrintf("tstCollector: getRawHostDiskLoad() -> %Rrc\n", rc);
+ return 1;
+ }
+ RTPrintf("tstCollector: host disk util = %llu msec (%u.%u %%), total = %llu msec\n\n",
+ (diskMsStop - diskMsStart),
+ (unsigned)((diskMsStop - diskMsStart) * 100 / (totalMsStop - totalMsStart)),
+ (unsigned)((diskMsStop - diskMsStart) * 10000 / (totalMsStop - totalMsStart) % 100),
+ totalMsStop - totalMsStart);
+
+ return 0;
+}
+
+
+
int main(int argc, char *argv[])
{
/*
* Initialize the VBox runtime without loading
* the support driver.
*/
- int rc = RTR3Init();
+ int rc = RTR3InitExe(argc, &argv, 0);
if (RT_FAILURE(rc))
{
- RTPrintf("tstCollector: RTR3Init() -> %d\n", rc);
+ RTPrintf("tstCollector: RTR3InitExe() -> %d\n", rc);
return 1;
}
if (argc > 1 && !strcmp(argv[1], "-child"))
@@ -243,11 +388,21 @@ int main(int argc, char *argv[])
printf("tstCollector: host cpu kernel = %f sec\n", (hostKernelStop - hostKernelStart) / 10000000.);
printf("tstCollector: host cpu idle = %f sec\n", (hostIdleStop - hostIdleStart) / 10000000.);
printf("tstCollector: host cpu total = %f sec\n", hostTotal / 10000000.);*/
- RTPrintf("tstCollector: host cpu user = %llu %%\n", (hostUserStop - hostUserStart) * 100 / hostTotal);
- RTPrintf("tstCollector: host cpu kernel = %llu %%\n", (hostKernelStop - hostKernelStart) * 100 / hostTotal);
- RTPrintf("tstCollector: host cpu idle = %llu %%\n", (hostIdleStop - hostIdleStart) * 100 / hostTotal);
- RTPrintf("tstCollector: process cpu user = %llu %%\n", (processUserStop - processUserStart) * 100 / (processTotalStop - processTotalStart));
- RTPrintf("tstCollector: process cpu kernel = %llu %%\n\n", (processKernelStop - processKernelStart) * 100 / (processTotalStop - processTotalStart));
+ RTPrintf("tstCollector: host cpu user = %u.%u %%\n",
+ (unsigned)((hostUserStop - hostUserStart) * 100 / hostTotal),
+ (unsigned)((hostUserStop - hostUserStart) * 10000 / hostTotal % 100));
+ RTPrintf("tstCollector: host cpu kernel = %u.%u %%\n",
+ (unsigned)((hostKernelStop - hostKernelStart) * 100 / hostTotal),
+ (unsigned)((hostKernelStop - hostKernelStart) * 10000 / hostTotal % 100));
+ RTPrintf("tstCollector: host cpu idle = %u.%u %%\n",
+ (unsigned)((hostIdleStop - hostIdleStart) * 100 / hostTotal),
+ (unsigned)((hostIdleStop - hostIdleStart) * 10000 / hostTotal % 100));
+ RTPrintf("tstCollector: process cpu user = %u.%u %%\n",
+ (unsigned)((processUserStop - processUserStart) * 100 / (processTotalStop - processTotalStart)),
+ (unsigned)((processUserStop - processUserStart) * 10000 / (processTotalStop - processTotalStart) % 100));
+ RTPrintf("tstCollector: process cpu kernel = %u.%u %%\n\n",
+ (unsigned)((processKernelStop - processKernelStart) * 100 / (processTotalStop - processTotalStart)),
+ (unsigned)((processKernelStop - processKernelStart) * 10000 / (processTotalStop - processTotalStart) % 100));
RTPrintf("tstCollector: TESTING - CPU load, looping for 5 sec\n");
rc = collector->preCollect(hints, 0);
@@ -292,11 +447,21 @@ int main(int argc, char *argv[])
hostTotal = hostUserStop - hostUserStart
+ hostKernelStop - hostKernelStart
+ hostIdleStop - hostIdleStart;
- RTPrintf("tstCollector: host cpu user = %llu %%\n", (hostUserStop - hostUserStart) * 100 / hostTotal);
- RTPrintf("tstCollector: host cpu kernel = %llu %%\n", (hostKernelStop - hostKernelStart) * 100 / hostTotal);
- RTPrintf("tstCollector: host cpu idle = %llu %%\n", (hostIdleStop - hostIdleStart) * 100 / hostTotal);
- RTPrintf("tstCollector: process cpu user = %llu %%\n", (processUserStop - processUserStart) * 100 / (processTotalStop - processTotalStart));
- RTPrintf("tstCollector: process cpu kernel = %llu %%\n\n", (processKernelStop - processKernelStart) * 100 / (processTotalStop - processTotalStart));
+ RTPrintf("tstCollector: host cpu user = %u.%u %%\n",
+ (unsigned)((hostUserStop - hostUserStart) * 100 / hostTotal),
+ (unsigned)((hostUserStop - hostUserStart) * 10000 / hostTotal % 100));
+ RTPrintf("tstCollector: host cpu kernel = %u.%u %%\n",
+ (unsigned)((hostKernelStop - hostKernelStart) * 100 / hostTotal),
+ (unsigned)((hostKernelStop - hostKernelStart) * 10000 / hostTotal % 100));
+ RTPrintf("tstCollector: host cpu idle = %u.%u %%\n",
+ (unsigned)((hostIdleStop - hostIdleStart) * 100 / hostTotal),
+ (unsigned)((hostIdleStop - hostIdleStart) * 10000 / hostTotal % 100));
+ RTPrintf("tstCollector: process cpu user = %u.%u %%\n",
+ (unsigned)((processUserStop - processUserStart) * 100 / (processTotalStop - processTotalStart)),
+ (unsigned)((processUserStop - processUserStart) * 10000 / (processTotalStop - processTotalStart) % 100));
+ RTPrintf("tstCollector: process cpu kernel = %u.%u %%\n\n",
+ (unsigned)((processKernelStop - processKernelStart) * 100 / (processTotalStop - processTotalStart)),
+ (unsigned)((processKernelStop - processKernelStart) * 10000 / (processTotalStop - processTotalStart) % 100));
RTPrintf("tstCollector: TESTING - Memory usage\n");
@@ -317,11 +482,22 @@ int main(int argc, char *argv[])
RTPrintf("tstCollector: host mem total = %lu kB\n", total);
RTPrintf("tstCollector: host mem used = %lu kB\n", used);
RTPrintf("tstCollector: host mem available = %lu kB\n", available);
- RTPrintf("tstCollector: process mem used = %lu kB\n", processUsed);
+ RTPrintf("tstCollector: process mem used = %lu kB\n\n", processUsed);
#endif
- RTPrintf("\ntstCollector: TESTING - Performance\n\n");
+#if 1
+ rc = testNetwork(collector);
+#endif
+#if 1
+ rc = testFsUsage(collector);
+#endif
+#if 1
+ rc = testDisk(collector);
+#endif
+#if 1
+ RTPrintf("tstCollector: TESTING - Performance\n\n");
measurePerformance(collector, argv[0], 100);
+#endif
delete collector;
diff --git a/src/VBox/Main/testcase/tstGuestCtrlContextID.cpp b/src/VBox/Main/testcase/tstGuestCtrlContextID.cpp
new file mode 100644
index 000000000..d7d748740
--- /dev/null
+++ b/src/VBox/Main/testcase/tstGuestCtrlContextID.cpp
@@ -0,0 +1,97 @@
+/* $Id: tstGuestCtrlContextID.cpp $ */
+
+/** @file
+ *
+ * Context ID makeup/extraction test cases.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#define LOG_ENABLED
+#define LOG_GROUP LOG_GROUP_MAIN
+#define LOG_INSTANCE NULL
+#include <VBox/log.h>
+
+#include "../include/GuestCtrlImplPrivate.h"
+
+using namespace com;
+
+#include <iprt/env.h>
+#include <iprt/rand.h>
+#include <iprt/stream.h>
+#include <iprt/test.h>
+
+int main()
+{
+ RTTEST hTest;
+ int rc = RTTestInitAndCreate("tstMakeup", &hTest);
+ if (rc)
+ return rc;
+ RTTestBanner(hTest);
+
+ RTTestIPrintf(RTTESTLVL_DEBUG, "Initializing COM...\n");
+ HRESULT hrc = com::Initialize();
+ if (FAILED(hrc))
+ {
+ RTTestFailed(hTest, "Failed to initialize COM (%Rhrc)!\n", hrc);
+ return RTEXITCODE_FAILURE;
+ }
+
+ /* Don't let the assertions trigger here
+ * -- we rely on the return values in the test(s) below. */
+ RTAssertSetQuiet(true);
+
+ uint32_t uContextMax = UINT32_MAX;
+ RTTestIPrintf(RTTESTLVL_DEBUG, "Max context is: %RU32\n", uContextMax);
+
+ /* Do 64 tests total. */
+ for (int t = 0; t < 64 && !RTTestErrorCount(hTest); t++)
+ {
+ /* VBOX_GUESTCTRL_MAX_* includes 0 as an object, so subtract one. */
+ uint32_t s = RTRandU32Ex(0, VBOX_GUESTCTRL_MAX_SESSIONS - 1);
+ uint32_t p = RTRandU32Ex(0, VBOX_GUESTCTRL_MAX_OBJECTS - 1);
+ uint32_t c = RTRandU32Ex(0, VBOX_GUESTCTRL_MAX_CONTEXTS - 1);
+
+ uint64_t uContextID = VBOX_GUESTCTRL_CONTEXTID_MAKE(s, p, c);
+ RTTestIPrintf(RTTESTLVL_DEBUG, "ContextID (%d,%d,%d) = %RU32\n", s, p, c, uContextID);
+ if (s != VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID))
+ {
+ RTTestFailed(hTest, "%d,%d,%d: Session is %d, expected %d -> %RU64\n",
+ s, p, c, VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID), s, uContextID);
+ }
+ else if (p != VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(uContextID))
+ {
+ RTTestFailed(hTest, "%d,%d,%d: Object is %d, expected %d -> %RU64\n",
+ s, p, c, VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(uContextID), p, uContextID);
+ }
+ if (c != VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID))
+ {
+ RTTestFailed(hTest, "%d,%d,%d: Count is %d, expected %d -> %RU64\n",
+ s, p, c, VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID), c, uContextID);
+ }
+ if (uContextID > UINT32_MAX)
+ {
+ RTTestFailed(hTest, "%d,%d,%d: Value overflow; does not fit anymore: %RU64\n",
+ s, p, c, uContextID);
+ }
+ }
+
+ RTTestIPrintf(RTTESTLVL_DEBUG, "Shutting down COM...\n");
+ com::Shutdown();
+
+ /*
+ * Summary.
+ */
+ return RTTestSummaryAndDestroy(hTest);
+}
+
diff --git a/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp b/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp
index f38d3cc1c..64dda8543 100644
--- a/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp
+++ b/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp
@@ -17,18 +17,15 @@
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "../include/GuestCtrlImplPrivate.h"
-
-using namespace com;
-
#define LOG_ENABLED
#define LOG_GROUP LOG_GROUP_MAIN
#define LOG_INSTANCE NULL
#include <VBox/log.h>
+#include "../include/GuestCtrlImplPrivate.h"
+
+using namespace com;
+
#include <iprt/env.h>
#include <iprt/test.h>
#include <iprt/stream.h>
@@ -207,12 +204,12 @@ int main()
iResult = stream.ParseBlock(curBlock);
if (iResult != aTestBlock[iTest].iResult)
{
- RTTestFailed(hTest, "\tReturned %Rrc, expected %Rrc",
+ RTTestFailed(hTest, "\tReturned %Rrc, expected %Rrc\n",
iResult, aTestBlock[iTest].iResult);
}
else if (stream.GetOffset() != aTestBlock[iTest].uOffsetAfter)
{
- RTTestFailed(hTest, "\tOffset %u wrong, expected %u",
+ RTTestFailed(hTest, "\tOffset %u wrong, expected %u\n",
stream.GetOffset(), aTestBlock[iTest].uOffsetAfter);
}
else if (iResult == VERR_MORE_DATA)
@@ -225,7 +222,7 @@ int main()
{
if (curBlock.GetCount() != aTestBlock[iTest].uMapElements)
{
- RTTestFailed(hTest, "\tMap has %u elements, expected %u",
+ RTTestFailed(hTest, "\tMap has %u elements, expected %u\n",
curBlock.GetCount(), aTestBlock[iTest].uMapElements);
}
}
@@ -277,7 +274,7 @@ int main()
if (iResult != aTestStream[iTest].iResult)
{
- RTTestFailed(hTest, "\tReturned %Rrc, expected %Rrc",
+ RTTestFailed(hTest, "\tReturned %Rrc, expected %Rrc\n",
iResult, aTestStream[iTest].iResult);
}
else if (uNumBlocks != aTestStream[iTest].uNumBlocks)
diff --git a/src/VBox/Main/testcase/tstOVF.cpp b/src/VBox/Main/testcase/tstOVF.cpp
index 7386f4083..9265b1e83 100644
--- a/src/VBox/Main/testcase/tstOVF.cpp
+++ b/src/VBox/Main/testcase/tstOVF.cpp
@@ -281,7 +281,7 @@ void copyDummyDiskImage(const char *pcszPrefix,
*/
int main(int argc, char *argv[])
{
- RTR3Init();
+ RTR3InitExe(argc, &argv, 0);
HRESULT rc = S_OK;
diff --git a/src/VBox/Main/testcase/tstVBoxAPILinux.cpp b/src/VBox/Main/testcase/tstVBoxAPILinux.cpp
index 6c7aa0fbe..4c4830ad6 100644
--- a/src/VBox/Main/testcase/tstVBoxAPILinux.cpp
+++ b/src/VBox/Main/testcase/tstVBoxAPILinux.cpp
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -190,9 +190,9 @@ void createVM(IVirtualBox *virtualBox)
nsCOMPtr<IMachine> machine;
rc = virtualBox->CreateMachine(NULL, /* settings file */
NS_LITERAL_STRING("A brand new name").get(),
+ 0, nsnull, /* groups (safearray)*/
nsnull, /* ostype */
- nsnull, /* machine uuid */
- false, /* forceOverwrite */
+ nsnull, /* create flags */
getter_AddRefs(machine));
if (NS_FAILED(rc))
{
diff --git a/src/VBox/Main/webservice/MANIFEST.MF.in b/src/VBox/Main/webservice/MANIFEST.MF.in
index b3a91ccca..89d7a5b25 100644
--- a/src/VBox/Main/webservice/MANIFEST.MF.in
+++ b/src/VBox/Main/webservice/MANIFEST.MF.in
@@ -6,5 +6,23 @@ Bundle-Version: @VBOX_VERSION_STRING@
Bundle-License: http://glassfish.java.net/nonav/public/CDDL+GPL.html
Bundle-ManifestVersion: 2
Tool: vi+sed
-Export-Package: org.virtualbox@VBOX_API_SUFFIX@;uses="javax.jws.soap,javax.xml,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.bind.util,javax,xml.namespace,javax.xml.parsers,javax.xml.stream,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.stream,javax.xml.ws,javax.xml.ws.handler,javax.xml.ws.http,javax.xml.ws.soap,javax.xml.ws.spi,javax.xml.ws.wsaddressing,org.w3c.dom,org.xml.sax";version="@VBOX_VERSION_STRING@"
-Import-Package:javax.validation.constraints;version="1.0",javax.jws,com.sun.xml.ws.developer,com.sun.xml.ws,com.sun.xml.ws.api.message,javax.jws.soap,javax.xml.namespace,javax.xml.ws,javax.xml.ws.spi,javax.xml.ws.soap,javax.xml.ws.handler,javax.xml.ws.http,javax.xml.ws.wsaddressing,javax.xml.parsers,javax.xml.stream,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.stream,org.w2c.dom,org.xml.sax,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.bind.util,org.virtualbox@VBOX_API_SUFFIX@;version="@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@"
+Export-Package: org.virtualbox@VBOX_API_SUFFIX@;uses="javax.jws.soap,
+ javax.xml,javax.xml.bind,javax.xml.bind.annotation,
+ javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.bind.util,
+ javax,xml.namespace,javax.xml.parsers,javax.xml.stream,
+ javax.xml.transform,javax.xml.transform.dom,
+ javax.xml.transform.stream,javax.xml.ws,javax.xml.ws.handler,
+ javax.xml.ws.http,javax.xml.ws.soap,javax.xml.ws.spi,
+ javax.xml.ws.wsaddressing,org.w3c.dom,org.xml.sax";
+ version="@VBOX_VERSION_STRING@"
+Import-Package: javax.validation.constraints;version="1.0",
+ javax.jws,com.sun.xml.ws.developer,
+ com.sun.xml.ws,com.sun.xml.ws.api.message,javax.jws.soap,
+ javax.xml.namespace,javax.xml.ws,javax.xml.ws.spi,
+ javax.xml.ws.soap,javax.xml.ws.handler,javax.xml.ws.http,
+ javax.xml.ws.wsaddressing,javax.xml.parsers,javax.xml.stream,
+ javax.xml.transform,javax.xml.transform.dom,
+ javax.xml.transform.stream,org.w2c.dom,org.xml.sax,javax.xml.bind,
+ javax.xml.bind.annotation,javax.xml.bind.attachment,
+ javax.xml.bind.helpers,javax.xml.bind.util,
+ org.virtualbox@VBOX_API_SUFFIX@;version="@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@"
diff --git a/src/VBox/Main/webservice/Makefile.kmk b/src/VBox/Main/webservice/Makefile.kmk
index e3b2de72c..17e50bcf2 100644
--- a/src/VBox/Main/webservice/Makefile.kmk
+++ b/src/VBox/Main/webservice/Makefile.kmk
@@ -6,7 +6,7 @@
#
#
-# Copyright (C) 2006-2012 Oracle Corporation
+# Copyright (C) 2007-2012 Oracle Corporation
#
# This file is part of VirtualBox Open Source Edition (OSE), as
# available from http://www.virtualbox.org. This file is free software;
@@ -162,7 +162,9 @@ PATH_TARGET_WEBTEST := $(VBOXWEB_OUT_DIR)/webtest
# the original XIDL file (has to include documentation as we need it):
VBOXWEB_IDL_SRC_ORIG := $(VBOX_XIDL_FILE_SRC)
-# platform-specific XIDL file generated from $(VBOXWEB_IDL_SRC):
+# the original XIDL file without documentation
+VBOXWEB_IDL_SRC_STRIPPED := $(VBOX_XIDL_FILE)
+# platform-specific XIDL file generated from $(VBOXWEB_IDL_SRC_STRIPPED):
VBOXWEB_IDL_SRC := $(VBOXWEB_OUT_DIR)/VirtualBox.xidl
VBOXWEB_WSDL = $(VBOX_PATH_SDK)/bindings/webservice/vboxweb.wsdl
@@ -206,9 +208,7 @@ ifdef VBOX_GSOAP_INSTALLED
#
LIBRARIES += vboxsoap
vboxsoap_TEMPLATE = VBOXWEBR3EXE
- ifdef VBOX_USE_VCC80
- vboxsoap_CXXFLAGS.win += -bigobj
- endif
+ vboxsoap_CXXFLAGS.win += -bigobj
ifn1of ($(KBUILD_TARGET), win)
vboxsoap_CXXFLAGS += -Wno-shadow
endif
@@ -291,9 +291,7 @@ endif
$(VBOX_GSOAP_INCS) \
$(VBOXWEB_OUT_DIR) \
.
- ifdef VBOX_USE_VCC80
- vboxwebsrv_CXXFLAGS.win += -bigobj
- endif
+ vboxwebsrv_CXXFLAGS.win += -bigobj
ifn1of ($(KBUILD_TARGET), win)
vboxwebsrv_CXXFLAGS += -Wno-shadow
endif
@@ -317,7 +315,6 @@ endif
$(VBOXWEB_OUT_DIR)/vboxweb-wsdl.c
vboxweb.cpp_DEFS = \
- VBOX_BUILD_TARGET=\"$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)\" \
$(if $(VBOX_BLEEDING_EDGE),VBOX_BLEEDING_EDGE=\"$(VBOX_BLEEDING_EDGE)\",)
vboxwebsrv_ORDERDEPS = $(VBOXWEB_OUT_DIR)/gsoap_copy_all_ts
@@ -374,7 +371,7 @@ $(VBOX_JWS_GEN)/jwsglue.list: \
$(VBOXWEB_WSDL) \
| $(VBOX_JWS_GEN)/java/
$(call MSG_L1,Generating JAX-WS Java glue files from XIDL)
- $(RM) -f $(wildcard $(VBOX_JWS_GEN)/java/*/*/*.java) $(wildcard $(VBOX_JWS_GEN)/java/*/*/*/*.java)
+ $(QUIET)$(RM) -f $(wildcard $(VBOX_JWS_GEN)/java/*/*/*.java) $(wildcard $(VBOX_JWS_GEN)/java/*/*/*/*.java)
$(QUIET)$(VBOX_XSLTPROC) \
--stringparam G_vboxApiSuffix $(VBOX_API_SUFFIX) \
--stringparam G_vboxGlueStyle jaxws \
@@ -398,7 +395,7 @@ $$(VBOX_JWS_JAR): $(VBOX_JWS_GEN)/jwsglue.list $(VBOXWEB_WSDL) $(VBOXWEBSERVICE_
$(QUIET)$(SED) -e "s/vboxweb.wsdl/vboxweb$(VBOX_API_SUFFIX).wsdl/" < $(VBOXWEBSERVICE_WSDL) > $(VBOX_JWS_JDEST)/vboxwebService$(VBOX_API_SUFFIX).wsdl
$(QUIET)$(CP) -f $(VBOXWEB_WSDL) $(VBOX_JWS_JDEST)/vboxweb$(VBOX_API_SUFFIX).wsdl
$(call MSG_LINK,$(notdir $@),$@)
- $(VBOX_JAR) cf $@ $(VBOX_JWS_GEN)/MANIFEST.MF -C $(VBOX_JWS_JDEST) .
+ $(VBOX_JAR) cfm $@ $(VBOX_JWS_GEN)/MANIFEST.MF -C $(VBOX_JWS_JDEST) .
$(VBOX_JWS_GEN)/MANIFEST.MF: $(VBOX_PATH_WEBSERVICE)/MANIFEST.MF.in
$(QUIET)$(RM) -f -- $@
@@ -435,9 +432,7 @@ $$(VBOX_JWSSRC_JAR): $$(VBOX_JWS_JAR) | $$(dir $$@)
#
PROGRAMS += webtest
webtest_TEMPLATE = VBOXWEBR3EXE
- ifdef VBOX_USE_VCC80
- webtest_CXXFLAGS.win += -bigobj
- endif
+ webtest_CXXFLAGS.win += -bigobj
ifn1of ($(KBUILD_TARGET), win)
webtest_CXXFLAGS += -Wno-shadow
endif
@@ -558,7 +553,7 @@ OTHER_CLEAN += \
$(VBOXWEB_IDL_SRC)
# generate platform-specific XIDL file from original XIDL file
-$(VBOXWEB_IDL_SRC): $(VBOXWEB_IDL_SRC_ORIG) $(VBOX_PATH_WEBSERVICE)/platform-xidl.xsl | $$(dir $$@)
+$(VBOXWEB_IDL_SRC): $(VBOXWEB_IDL_SRC_STRIPPED) $(VBOX_PATH_WEBSERVICE)/platform-xidl.xsl | $$(dir $$@)
$(call MSG_GENERATE,,$@,$(VBOXWEB_IDL_SRC) using platform-xidl.xsl)
$(QUIET)$(RM) -f -- $@
$(QUIET)$(VBOX_XSLTPROC) $(VBOXWEB_XSLTPROC_VERBOSE) -o $@ $(VBOX_PATH_WEBSERVICE)/platform-xidl.xsl $<
@@ -739,4 +734,4 @@ $(VBOXWEB_METRICSAMPLE): $(VBOX_PATH_WEBSERVICE)/samples/java/jax-ws/metrictest.
endif # VBOX_ONLY_SDK
-include $(KBUILD_PATH)/subfooter.kmk
+include $(FILE_KBUILD_SUB_FOOTER)
diff --git a/src/VBox/Main/webservice/platform-xidl.xsl b/src/VBox/Main/webservice/platform-xidl.xsl
index f168fdb99..48dce42a7 100644
--- a/src/VBox/Main/webservice/platform-xidl.xsl
+++ b/src/VBox/Main/webservice/platform-xidl.xsl
@@ -8,15 +8,15 @@
is identical to the original except that all <if...>
sections are resolved (for easier processing).
- Copyright (C) 2006-2011 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2011 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet
diff --git a/src/VBox/Main/webservice/samples/perl/clienttest.pl b/src/VBox/Main/webservice/samples/perl/clienttest.pl
index a2877962f..72c69e458 100755
--- a/src/VBox/Main/webservice/samples/perl/clienttest.pl
+++ b/src/VBox/Main/webservice/samples/perl/clienttest.pl
@@ -5,7 +5,7 @@
# webservice and calls various methods on it. Please refer to the SDK
# programming reference (SDKRef.pdf) for how to use this sample.
#
-# Copyright (C) 2008-2010 Oracle Corporation
+# Copyright (C) 2008-2012 Oracle Corporation
#
# The following license applies to this file only:
#
@@ -50,7 +50,9 @@ while (my $this = shift(@ARGV))
"with <mode> being one of 'version', 'list', 'start'; default is 'list'.\n".
" $cmd version: print version of VirtualBox web service.\n".
" $cmd list: list installed virtual machines.\n".
- " $cmd startvm <vm>: start the virtual machine named <vm>.\n";
+ " $cmd startvm <vm>: start the virtual machine named <vm>.\n".
+ " $cmd acpipowerbutton <vm>: shutdown of the irtual machine named <vm>.\n";
+ " $cmd openhd <disk>: open disk image <disk>.\n";
exit 0;
}
elsif ( ($this eq 'version')
@@ -59,7 +61,9 @@ while (my $this = shift(@ARGV))
{
$optMode = $this;
}
- elsif ($this eq 'startvm')
+ elsif ( ($this eq 'startvm')
+ || ($this eq 'acpipowerbutton')
+ )
{
$optMode = $this;
@@ -86,6 +90,50 @@ while (my $this = shift(@ARGV))
$optMode = "list"
if (!$optMode);
+# SOAP::Lite hacking to make it serialize the enum types we use correctly.
+# In the long run, this needs to be done either by stubmaker.pl or something
+# else, because the WSDL clearly says they're restricted strings. Quite silly
+# that the default behavior is to ignore the parameter and just let the server
+# use the default value for the type.
+
+sub SOAP::Serializer::as_LockType
+{
+ my ($self, $value, $name, $type, $attr) = @_;
+ die "String value expected instead of @{[ref $value]} reference\n"
+ if ref $value;
+ return [
+ $name,
+ {'xsi:type' => 'vbox:LockType', %$attr},
+ SOAP::Utils::encode_data($value)
+ ];
+}
+
+sub SOAP::Serializer::as_DeviceType
+{
+ my ($self, $value, $name, $type, $attr) = @_;
+ die "String value expected instead of @{[ref $value]} reference\n"
+ if ref $value;
+ return [
+ $name,
+ {'xsi:type' => 'vbox:DeviceType', %$attr},
+ SOAP::Utils::encode_data($value)
+ ];
+}
+
+sub SOAP::Serializer::as_AccessMode
+{
+ my ($self, $value, $name, $type, $attr) = @_;
+ die "String value expected instead of @{[ref $value]} reference\n"
+ if ref $value;
+ return [
+ $name,
+ {'xsi:type' => 'vbox:AccessMode', %$attr},
+ SOAP::Utils::encode_data($value)
+ ];
+}
+
+## @todo needs much more error handling, e.g. openhd never complains
+
my $vbox = vboxService->IWebsessionManager_logon("test", "test");
if (!$vbox)
@@ -112,13 +160,7 @@ elsif ($optMode eq "list")
}
elsif ($optMode eq "startvm")
{
- # assume it's a UUID
- my $machine = vboxService->IVirtualBox_getMachine($vbox, $vmname);
- if (!$machine)
- {
- # no: then try a name
- $machine = vboxService->IVirtualBox_findMachine($vbox, $vmname);
- }
+ my $machine = vboxService->IVirtualBox_findMachine($vbox, $vmname);
die "[$cmd] Cannot find VM \"$vmname\"; stopped"
if (!$machine);
@@ -133,15 +175,14 @@ elsif ($optMode eq "startvm")
print "[$cmd] UUID: $uuid\n";
- my $progress = vboxService->IVirtualBox_openRemoteSession($vbox,
- $session,
- $uuid,
- "vrdp",
- "");
- die "[$cmd] Cannot open remote session; stopped"
+ my $progress = vboxService->IMachine_launchVMProcess($machine,
+ $session,
+ "headless",
+ "");
+ die "[$cmd] Cannot launch VM; stopped"
if (!$progress);
- print("[$cmd] Waiting for the remote session to open...\n");
+ print("[$cmd] Waiting for the VM to start...\n");
vboxService->IProgress_waitForCompletion($progress, -1);
my $fCompleted;
@@ -153,11 +194,35 @@ elsif ($optMode eq "startvm")
print("[$cmd] Result: $resultCode\n");
- vboxService->ISession_close($session);
+ vboxService->ISession_unlockMachine($session);
+
+ vboxService->IWebsessionManager_logoff($vbox);
+}
+elsif ($optMode eq "acpipowerbutton")
+{
+ my $machine = vboxService->IVirtualBox_findMachine($vbox, $vmname);
+
+ die "[$cmd] Cannot find VM \"$vmname\"; stopped"
+ if (!$machine);
+
+ my $session = vboxService->IWebsessionManager_getSessionObject($vbox);
+ die "[$cmd] Cannot get session object; stopped"
+ if (!$session);
+
+ vboxService->IMachine_lockMachine($machine, $session, 'Shared');
+
+ my $console = vboxService->ISession_getConsole($session);
+
+ vboxService->IConsole_powerButton($console);
+
+ vboxService->ISession_unlockMachine($session);
vboxService->IWebsessionManager_logoff($vbox);
}
elsif ($optMode eq "openhd")
{
- my $harddisk = vboxService->IVirtualBox_openHardDisk($vbox, $disk, 1, 0, "", 0, "");
+ my $medium = vboxService->IVirtualBox_openMedium($vbox, $disk,
+ 'HardDisk',
+ 'ReadWrite',
+ 0);
}
diff --git a/src/VBox/Main/webservice/vboxweb.cpp b/src/VBox/Main/webservice/vboxweb.cpp
index e1c368393..33394f21e 100644
--- a/src/VBox/Main/webservice/vboxweb.cpp
+++ b/src/VBox/Main/webservice/vboxweb.cpp
@@ -5,7 +5,7 @@
* (plus static gSOAP server code) to implement the actual webservice
* server, to which clients can connect.
*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2007-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -31,8 +31,6 @@
#include <VBox/version.h>
#include <VBox/log.h>
-#include <package-generated.h>
-
#include <iprt/buildconfig.h>
#include <iprt/ctype.h>
#include <iprt/getopt.h>
@@ -50,6 +48,7 @@
#include <iprt/system.h>
#include <iprt/base64.h>
#include <iprt/stream.h>
+#include <iprt/asm.h>
// workaround for compile problems on gcc 4.1
#ifdef __GNUC__
@@ -143,9 +142,7 @@ uint32_t g_uHistoryFileTime = RT_SEC_1DAY; // max 1 day per file
uint64_t g_uHistoryFileSize = 100 * _1M; // max 100MB per file
bool g_fVerbose = false; // be verbose
-#if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
bool g_fDaemonize = false; // run in background.
-#endif
const WSDLT_ID g_EmptyWSDLID; // for NULL MORs
@@ -681,10 +678,9 @@ typedef ListenerImpl<VirtualBoxClientEventListener> VirtualBoxClientEventListene
VBOX_LISTENER_DECLARE(VirtualBoxClientEventListenerImpl)
/**
- * Implementation for WEBLOG macro defined in vboxweb.h; this prints a message
- * to the console and optionally to the file that may have been given to the
- * vboxwebsrv command line.
+ * Prints a message to the webservice log file.
* @param pszFormat
+ * @todo eliminate, has no significant additional value over direct calls to LogRel.
*/
void WebLog(const char *pszFormat, ...)
{
@@ -719,74 +715,6 @@ void WebLogSoapError(struct soap *soap)
(ppcszDetail && *ppcszDetail) ? *ppcszDetail : "no details available");
}
-static void WebLogHeaderFooter(PRTLOGGER pLoggerRelease, RTLOGPHASE enmPhase, PFNRTLOGPHASEMSG pfnLog)
-{
- /* some introductory information */
- static RTTIMESPEC s_TimeSpec;
- char szTmp[256];
- if (enmPhase == RTLOGPHASE_BEGIN)
- RTTimeNow(&s_TimeSpec);
- RTTimeSpecToString(&s_TimeSpec, szTmp, sizeof(szTmp));
-
- switch (enmPhase)
- {
- case RTLOGPHASE_BEGIN:
- {
- pfnLog(pLoggerRelease,
- "VirtualBox web service %s r%u %s (%s %s) release log\n"
-#ifdef VBOX_BLEEDING_EDGE
- "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n"
-#endif
- "Log opened %s\n",
- VBOX_VERSION_STRING, RTBldCfgRevision(), VBOX_BUILD_TARGET,
- __DATE__, __TIME__, szTmp);
-
- int vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- pfnLog(pLoggerRelease, "OS Product: %s\n", szTmp);
- vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- pfnLog(pLoggerRelease, "OS Release: %s\n", szTmp);
- vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- pfnLog(pLoggerRelease, "OS Version: %s\n", szTmp);
- if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
- pfnLog(pLoggerRelease, "OS Service Pack: %s\n", szTmp);
-
- /* the package type is interesting for Linux distributions */
- char szExecName[RTPATH_MAX];
- char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
- pfnLog(pLoggerRelease,
- "Executable: %s\n"
- "Process ID: %u\n"
- "Package type: %s"
-#ifdef VBOX_OSE
- " (OSE)"
-#endif
- "\n",
- pszExecName ? pszExecName : "unknown",
- RTProcSelf(),
- VBOX_PACKAGE_STRING);
- break;
- }
-
- case RTLOGPHASE_PREROTATE:
- pfnLog(pLoggerRelease, "Log rotated - Log started %s\n", szTmp);
- break;
-
- case RTLOGPHASE_POSTROTATE:
- pfnLog(pLoggerRelease, "Log continuation - Log started %s\n", szTmp);
- break;
-
- case RTLOGPHASE_END:
- pfnLog(pLoggerRelease, "End of log file - Log started %s\n", szTmp);
- break;
-
- default:
- /* nothing */;
- }
-}
-
#ifdef WITH_OPENSSL
/****************************************************************************
*
@@ -816,9 +744,12 @@ static void CRYPTO_locking_function(int mode, int n, const char * /*file*/, int
static struct CRYPTO_dynlock_value *CRYPTO_dyn_create_function(const char * /*file*/, int /*line*/)
{
+ static uint32_t s_iCritSectDynlock = 0;
struct CRYPTO_dynlock_value *value = (struct CRYPTO_dynlock_value *)RTMemAlloc(sizeof(struct CRYPTO_dynlock_value));
if (value)
- RTCritSectInit(&value->mutex);
+ RTCritSectInitEx(&value->mutex, RTCRITSECT_FLAGS_NO_LOCK_VAL,
+ NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE,
+ "openssl-dyn-%u", ASMAtomicIncU32(&s_iCritSectDynlock) - 1);
return value;
}
@@ -849,7 +780,9 @@ static int CRYPTO_thread_setup()
for (int i = 0; i < num_locks; i++)
{
- int rc = RTCritSectInit(&g_pSSLMutexes[i]);
+ int rc = RTCritSectInitEx(&g_pSSLMutexes[i], RTCRITSECT_FLAGS_NO_LOCK_VAL,
+ NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE,
+ "openssl-%d", i);
if (RT_FAILURE(rc))
{
for ( ; i >= 0; i--)
@@ -1006,15 +939,15 @@ static CComModule _Module;
int main(int argc, char *argv[])
{
// initialize runtime
- int rc = RTR3Init();
+ int rc = RTR3InitExe(argc, &argv, 0);
if (RT_FAILURE(rc))
return RTMsgInitFailure(rc);
// store a log prefix for this thread
g_mapThreads[RTThreadSelf()] = "[M ]";
- RTStrmPrintf(g_pStdErr, VBOX_PRODUCT " web service version " VBOX_VERSION_STRING "\n"
- "(C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
+ RTStrmPrintf(g_pStdErr, VBOX_PRODUCT " web service Version " VBOX_VERSION_STRING "\n"
+ "(C) 2007-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
"All rights reserved.\n");
int c;
@@ -1156,28 +1089,16 @@ int main(int argc, char *argv[])
}
}
- /* create release logger */
- PRTLOGGER pLoggerRelease;
- static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
- RTUINT fFlags = RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG;
-#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
- fFlags |= RTLOGFLAGS_USECRLF;
-#endif
- char szError[RTPATH_MAX + 128] = "";
- int vrc = RTLogCreateEx(&pLoggerRelease, fFlags, "all",
- "VBOXWEBSRV_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_STDOUT,
- WebLogHeaderFooter, g_cHistory, g_uHistoryFileSize, g_uHistoryFileTime,
- szError, sizeof(szError), pszLogFile);
- if (RT_SUCCESS(vrc))
- {
- /* register this logger as the release logger */
- RTLogRelSetDefaultInstance(pLoggerRelease);
-
- /* Explicitly flush the log in case of VBOXWEBSRV_RELEASE_LOG=buffered. */
- RTLogFlush(pLoggerRelease);
- }
- else
- return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, vrc);
+ /* create release logger, to stdout */
+ char szError[RTPATH_MAX + 128];
+ rc = com::VBoxLogRelCreate("web service", g_fDaemonize ? NULL : pszLogFile,
+ RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG,
+ "all", "VBOXWEBSRV_RELEASE_LOG",
+ RTLOGDEST_STDOUT, UINT32_MAX /* cMaxEntriesPerGroup */,
+ g_cHistory, g_uHistoryFileTime, g_uHistoryFileSize,
+ szError, sizeof(szError));
+ if (RT_FAILURE(rc))
+ return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, rc);
#if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
if (g_fDaemonize)
@@ -1185,39 +1106,30 @@ int main(int argc, char *argv[])
/* prepare release logging */
char szLogFile[RTPATH_MAX];
- rc = com::GetVBoxUserHomeDirectory(szLogFile, sizeof(szLogFile));
- if (RT_FAILURE(rc))
- return RTMsgErrorExit(RTEXITCODE_FAILURE, "could not get base directory for logging: %Rrc", rc);
- rc = RTPathAppend(szLogFile, sizeof(szLogFile), "vboxwebsrv.log");
- if (RT_FAILURE(rc))
- return RTMsgErrorExit(RTEXITCODE_FAILURE, "could not construct logging path: %Rrc", rc);
+ if (!pszLogFile || !*pszLogFile)
+ {
+ rc = com::GetVBoxUserHomeDirectory(szLogFile, sizeof(szLogFile));
+ if (RT_FAILURE(rc))
+ return RTMsgErrorExit(RTEXITCODE_FAILURE, "could not get base directory for logging: %Rrc", rc);
+ rc = RTPathAppend(szLogFile, sizeof(szLogFile), "vboxwebsrv.log");
+ if (RT_FAILURE(rc))
+ return RTMsgErrorExit(RTEXITCODE_FAILURE, "could not construct logging path: %Rrc", rc);
+ pszLogFile = szLogFile;
+ }
rc = RTProcDaemonizeUsingFork(false /* fNoChDir */, false /* fNoClose */, pszPidFile);
if (RT_FAILURE(rc))
return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to daemonize, rc=%Rrc. exiting.", rc);
- /* create release logger */
- PRTLOGGER pLoggerReleaseFile;
- static const char * const s_apszGroupsFile[] = VBOX_LOGGROUP_NAMES;
- RTUINT fFlagsFile = RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG;
-#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
- fFlagsFile |= RTLOGFLAGS_USECRLF;
-#endif
- char szErrorFile[RTPATH_MAX + 128] = "";
- int vrc = RTLogCreateEx(&pLoggerReleaseFile, fFlagsFile, "all",
- "VBOXWEBSRV_RELEASE_LOG", RT_ELEMENTS(s_apszGroupsFile), s_apszGroupsFile, RTLOGDEST_FILE,
- WebLogHeaderFooter, g_cHistory, g_uHistoryFileSize, g_uHistoryFileTime,
- szErrorFile, sizeof(szErrorFile), szLogFile);
- if (RT_SUCCESS(vrc))
- {
- /* register this logger as the release logger */
- RTLogRelSetDefaultInstance(pLoggerReleaseFile);
-
- /* Explicitly flush the log in case of VBOXWEBSRV_RELEASE_LOG=buffered. */
- RTLogFlush(pLoggerReleaseFile);
- }
- else
- return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szErrorFile, vrc);
+ /* create release logger, to file */
+ rc = com::VBoxLogRelCreate("web service", pszLogFile,
+ RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG,
+ "all", "VBOXWEBSRV_RELEASE_LOG",
+ RTLOGDEST_FILE, UINT32_MAX /* cMaxEntriesPerGroup */,
+ g_cHistory, g_uHistoryFileTime, g_uHistoryFileSize,
+ szError, sizeof(szError));
+ if (RT_FAILURE(rc))
+ return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, rc);
}
#endif
@@ -1524,17 +1436,25 @@ std::string Base64EncodeByteArray(ComSafeArrayIn(BYTE, aData))
return aStr.c_str();
}
-
-void Base64DecodeByteArray(std::string& aStr, ComSafeArrayOut(BYTE, aData))
+#define DECODE_STR_MAX 0x100000
+void Base64DecodeByteArray(struct soap *soap, std::string& aStr, ComSafeArrayOut(BYTE, aData))
{
const char* pszStr = aStr.c_str();
ssize_t cbOut = RTBase64DecodedSize(pszStr, NULL);
- Assert(cbOut > 0);
+ if(cbOut > DECODE_STR_MAX)
+ {
+ WebLog("Decode string too long.\n");
+ RaiseSoapRuntimeFault(soap, VERR_BUFFER_OVERFLOW, (ComPtr<IUnknown>)NULL);
+ }
com::SafeArray<BYTE> result(cbOut);
int rc = RTBase64Decode(pszStr, result.raw(), cbOut, NULL, NULL);
- AssertRC(rc);
+ if (FAILED(rc))
+ {
+ WebLog("String Decoding Failed. ERROR: 0x%lX\n", rc);
+ RaiseSoapRuntimeFault(soap, rc, (ComPtr<IUnknown>)NULL);
+ }
result.detachTo(ComSafeArrayOutArg(aData));
}
@@ -1554,9 +1474,9 @@ void RaiseSoapRuntimeFault2(struct soap *soap,
WEBDEBUG((" error, raising SOAP exception\n"));
- RTStrmPrintf(g_pStdErr, "API return code: 0x%08X (%Rhrc)\n", apirc, apirc);
- RTStrmPrintf(g_pStdErr, "COM error info result code: 0x%lX\n", info.getResultCode());
- RTStrmPrintf(g_pStdErr, "COM error info text: %ls\n", info.getText().raw());
+ WebLog("API return code: 0x%08X (%Rhrc)\n", apirc, apirc);
+ WebLog("COM error info result code: 0x%lX\n", info.getResultCode());
+ WebLog("COM error info text: %ls\n", info.getText().raw());
// allocated our own soap fault struct
_vbox__RuntimeFault *ex = soap_new__vbox__RuntimeFault(soap, 1);
diff --git a/src/VBox/Main/webservice/vboxweb.h b/src/VBox/Main/webservice/vboxweb.h
index 9803e8797..0309c3932 100644
--- a/src/VBox/Main/webservice/vboxweb.h
+++ b/src/VBox/Main/webservice/vboxweb.h
@@ -98,7 +98,7 @@ std::string ConvertComString(const com::Guid &bstr);
std::string Base64EncodeByteArray(ComSafeArrayIn(BYTE, aData));
-void Base64DecodeByteArray(std::string& aStr, ComSafeArrayOut(BYTE, aData));
+void Base64DecodeByteArray(struct soap *soap, std::string& aStr, ComSafeArrayOut(BYTE, aData));
/****************************************************************************
*
* managed object reference classes
diff --git a/src/VBox/Main/webservice/websrv-cpp.xsl b/src/VBox/Main/webservice/websrv-cpp.xsl
index 9f71374d3..1700e5af3 100644
--- a/src/VBox/Main/webservice/websrv-cpp.xsl
+++ b/src/VBox/Main/webservice/websrv-cpp.xsl
@@ -11,15 +11,15 @@
See webservice/Makefile.kmk for an overview of all the things
generated for the webservice.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2007-2012 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet
@@ -67,7 +67,6 @@
#include <VBox/com/errorprint.h>
#include <VBox/com/EventQueue.h>
#include <VBox/VBoxAuth.h>
-#include <VBox/version.h>
#include <iprt/assert.h>
#include <iprt/initterm.h>
@@ -245,7 +244,7 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:call-template name="emitNewline" />
<xsl:value-of select="concat('// COM interface ', $structname, ', which has wsmap=&quot;struct&quot;, to SOAP structures')" />
<xsl:call-template name="emitNewline" />
- <xsl:value-of select="concat('vbox__', $structname, '* ', $G_funcPrefixOutputEnumConverter, $structname, '(')" />
+ <xsl:value-of select="concat('vbox__', $structname, '* ', $G_funcPrefixOutputStructConverter, $structname, '(')" />
<xsl:call-template name="emitNewline" />
<xsl:value-of select="' struct soap *soap,'" />
<xsl:call-template name="emitNewline" />
@@ -265,6 +264,12 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:value-of select="concat(' resp = soap_new_vbox__', $structname, '(soap, -1);')" />
<xsl:call-template name="emitNewline" />
+ <xsl:text> if (!in)&#10;</xsl:text>
+ <xsl:text> {&#10;</xsl:text>
+ <xsl:text> // @todo ambiguous. Problem is the MOR for the object converted to struct&#10;</xsl:text>
+ <xsl:text> RaiseSoapInvalidObjectFault(soap, "");&#10;</xsl:text>
+ <xsl:text> break;&#10;</xsl:text>
+ <xsl:text> }&#10;</xsl:text>
<xsl:call-template name="emitNewline" />
<xsl:for-each select="//interface[@name=$structname]/attribute">
@@ -534,14 +539,14 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:param name="type" />
<xsl:param name="safearray" />
- <xsl:value-of select="concat(' // convert input arg ', $name)" />
+ <xsl:value-of select="concat(' // convert input arg ', $name, '(safearray: ', $safearray, ')')" />
<xsl:call-template name="emitNewlineIndent8" />
- <xsl:choose>
+ <xsl:choose>
<xsl:when test="$safearray='yes' and $type='octet'">
<xsl:value-of select="concat('com::SafeArray&lt;BYTE&gt; comcall_',$name, ';')" />
<xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat('Base64DecodeByteArray(',$structprefix,$name,', ComSafeArrayAsOutParam(comcall_',$name, '));')" />
+ <xsl:value-of select="concat('Base64DecodeByteArray(soap, ',$structprefix,$name,', ComSafeArrayAsOutParam(comcall_',$name, '));')" />
</xsl:when>
<xsl:when test="$safearray='yes'">
@@ -598,7 +603,7 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:when test="//enum[@name=$type]">
<xsl:call-template name="emitNewlineIndent8" />
<xsl:value-of select="concat(' comcall_', $name, '[i] = ', $G_funcPrefixInputEnumConverter, $type, '(', $structprefix, $name, '[i]);')" />
- </xsl:when>
+ </xsl:when>
<xsl:otherwise>
<xsl:call-template name="fatalError">
<xsl:with-param name="msg" select="concat('emitInputArgConverter Type &quot;', $type, '&quot; in arg &quot;', $name, '&quot; of method &quot;', $method, '&quot; is not yet supported in safearrays.')" />
@@ -630,9 +635,9 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:call-template name="emitNewlineIndent8" />
<xsl:text> break</xsl:text>
</xsl:when>
- <xsl:when test="(//interface[@name=$type]) or (//collection[@name=$type])">
+ <xsl:when test="//interface[@name=$type]">
<!-- the type is one of our own interfaces: then it must have a wsmap attr -->
- <xsl:variable name="thatif" select="(//interface[@name=$type]) | (//collection[@name=$type])" />
+ <xsl:variable name="thatif" select="//interface[@name=$type]" />
<xsl:variable name="wsmap" select="$thatif/@wsmap" />
<xsl:variable name="thatifname" select="$thatif/@name" />
<xsl:choose>
@@ -709,6 +714,30 @@ const char *g_pcszIUnknown = "IUnknown";
</xsl:template>
<!--
+ emitInParam:
+-->
+<xsl:template name="emitInParam">
+ <xsl:param name="name" />
+ <xsl:param name="type" />
+ <xsl:param name="safearray" />
+ <xsl:param name="varprefix" /> <!-- only with nested set-attribute calls -->
+
+ <xsl:variable name="varname" select="concat('comcall_', $varprefix, $name)" />
+
+ <xsl:choose>
+ <xsl:when test="@safearray='yes'">
+ <xsl:value-of select="concat('ComSafeArrayAsInParam(', $varname, ')')" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$varname" />
+ <xsl:if test="@type='wstring' or @type='uuid'">
+ <xsl:text>.raw()</xsl:text>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!--
emitOutParam:
-->
<xsl:template name="emitOutParam">
@@ -768,10 +797,12 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:if test="$attrtype">
<xsl:choose>
<xsl:when test="$attrdir='in'">
- <xsl:value-of select="concat('comcall_', $varprefix, @name)" />
- <xsl:if test="$attrtype='wstring' or $attrtype='uuid'">
- <xsl:text>.raw()</xsl:text>
- </xsl:if>
+ <xsl:call-template name="emitInParam">
+ <xsl:with-param name="name" select="$attrname" />
+ <xsl:with-param name="type" select="$attrtype" />
+ <xsl:with-param name="safearray" select="$attrsafearray" />
+ <xsl:with-param name="varprefix" select="$varprefix" />
+ </xsl:call-template>
</xsl:when>
<xsl:when test="$attrdir='return'">
<xsl:call-template name="emitOutParam">
@@ -794,17 +825,12 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="@dir='in'">
- <xsl:choose>
- <xsl:when test="@safearray='yes'">
- <xsl:value-of select="concat('ComSafeArrayAsInParam(comcall_', $varprefix, @name, ')')" />
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="concat('comcall_', $varprefix, @name)" />
- <xsl:if test="@type='wstring' or @type='uuid'">
- <xsl:text>.raw()</xsl:text>
- </xsl:if>
- </xsl:otherwise>
- </xsl:choose>
+ <xsl:call-template name="emitInParam">
+ <xsl:with-param name="name" select="@name" />
+ <xsl:with-param name="type" select="@type" />
+ <xsl:with-param name="safearray" select="@safearray" />
+ <xsl:with-param name="varprefix" select="$varprefix" />
+ </xsl:call-template>
</xsl:when>
<xsl:when test="@dir='out'">
<xsl:call-template name="emitOutParam">
@@ -887,7 +913,7 @@ const char *g_pcszIUnknown = "IUnknown";
<!-- prevent infinite recursion -->
<!-- <xsl:call-template name="fatalError"><xsl:with-param name="msg" select="concat('emitOutputArgBackConverter2: attempted infinite recursion for type &quot;', $type, '&quot; in arg &quot;', $name, '&quot; of method &quot;', $ifname, '::', $method)" /></xsl:call-template> -->
<xsl:if test="not($callerprefix)">
- <xsl:value-of select="concat('/* convert COM interface to struct */ ', $G_funcPrefixOutputEnumConverter, $type, '(soap, idThis, rc, ', $varname, ')')" />
+ <xsl:value-of select="concat('/* convert COM interface to struct */ ', $G_funcPrefixOutputStructConverter, $type, '(soap, idThis, rc, ', $varname, ')')" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
@@ -897,49 +923,6 @@ const char *g_pcszIUnknown = "IUnknown";
</xsl:otherwise>
</xsl:choose>
</xsl:when>
- <xsl:when test="//collection[@name=$type]">
- <!-- the type is a collection of our own types: then build an array from it -->
- <xsl:variable name="collectiontype" select="//collection[@name=$type]/@type" />
- <xsl:variable name="targetwsmap" select="//interface[@name=$collectiontype]/@wsmap" />
- <xsl:value-of select="concat('soap_new_vbox__ArrayOf', $collectiontype, '(soap, -1);')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:variable name="enumerator" select="concat('comcall_', $callerprefix, $name, '_enum')" />
- <xsl:value-of select="concat('ComPtr&lt;', $collectiontype, 'Enumerator&gt; ', $enumerator, ';')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat('CHECK_ERROR_BREAK( comcall_', $callerprefix, $name, ', Enumerate(', $enumerator, '.asOutParam()) );')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat('BOOL comcall_', $callerprefix, $name, '_hasmore = FALSE;')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="'do {'" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat(' CHECK_ERROR_BREAK( ', $enumerator, ', HasMore(&amp;comcall_', $callerprefix, $name, '_hasmore) );')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat(' if (!comcall_', $callerprefix, $name, '_hasmore) break;')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat(' ComPtr&lt;', $collectiontype, '&gt; arrayitem;')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat(' CHECK_ERROR_BREAK( ', $enumerator, ', GetNext(arrayitem.asOutParam()) );')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat(' // collection of &quot;', $collectiontype, '&quot;, target interface wsmap: &quot;', $targetwsmap, '&quot;')" />
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="concat(' ', $G_responseElementVarName, '-&gt;', $G_result)" />
- <xsl:value-of select="'->array.push_back('" />
- <xsl:choose>
- <xsl:when test="($targetwsmap='managed')">
- <xsl:value-of select="concat('createOrFindRefFromComPtr(idThis, g_pcsz', $collectiontype, ', arrayitem));')" />
- </xsl:when>
- <xsl:when test="$targetwsmap='struct'">
- <xsl:value-of select="concat($G_funcPrefixOutputEnumConverter, $collectiontype, '(soap, idThis, rc, arrayitem));')" />
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="fatalError">
- <xsl:with-param name="msg" select="concat('emitOutputArgBackConverter2: Type &quot;', $collectiontype, '&quot; of collection &quot;', $type, '&quot;, used in method &quot;', $method, '&quot;, has unsupported wsmap &quot;', $targetwsmap, '&quot;.')" />
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
- <xsl:call-template name="emitNewlineIndent8" />
- <xsl:value-of select="'} while (1)'" />
- </xsl:when>
<xsl:otherwise>
<xsl:call-template name="fatalError">
<xsl:with-param name="msg" select="concat('emitOutputArgBackConverter2: Type &quot;', $type, '&quot; in arg &quot;', $name, '&quot; of method &quot;', $method, '&quot; is not supported.')" />
@@ -992,7 +975,7 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:choose>
<xsl:when test="$safearray='yes' and $type='octet'">
- <xsl:value-of select="concat($receiverVariable, ' = Base64EncodeByteArray(ComSafeArrayAsInParam(', $varname,'));')" />
+ <xsl:value-of select="concat($receiverVariable, ' = Base64EncodeByteArray(ComSafeArrayAsInParam(', $varname,'));')" />
<xsl:call-template name="emitNewlineIndent8" />
</xsl:when>
@@ -1204,6 +1187,7 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:param name="attrname" select="$attrname" />
<xsl:param name="attrtype" select="$attrtype" />
<xsl:param name="attrreadonly" select="$attrreadonly" />
+ <xsl:param name="attrsafearray" select="$attrsafearray" />
<xsl:variable name="settername"><xsl:call-template name="makeSetterName"><xsl:with-param name="attrname" select="$attrname" /></xsl:call-template></xsl:variable>
@@ -1223,6 +1207,7 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:text>{</xsl:text>
<xsl:call-template name="emitNewline" />
<xsl:value-of select="' HRESULT rc = S_OK;'" />
+ <xsl:value-of select="concat(concat(' NOREF(', $G_responseElementVarName),');')" />
<xsl:call-template name="emitNewline" />
<xsl:call-template name="emitPrologue" />
@@ -1243,6 +1228,7 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:with-param name="object" select='"pObj"' />
<xsl:with-param name="attrname"><xsl:value-of select="$attrname" /></xsl:with-param>
<xsl:with-param name="attrtype"><xsl:value-of select="$attrtype" /></xsl:with-param>
+ <xsl:with-param name="attrsafearray"><xsl:value-of select="$attrsafearray" /></xsl:with-param>
</xsl:call-template>
<!-- </xsl:otherwise>
</xsl:choose> -->
@@ -1315,6 +1301,7 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:with-param name="attrname" select="$attrname" />
<xsl:with-param name="attrtype" select="$attrtype" />
<xsl:with-param name="attrreadonly" select="$attrreadonly" />
+ <xsl:with-param name="attrsafearray" select="$attrsafearray" />
</xsl:call-template>
</xsl:if>
</xsl:otherwise> <!-- not wsmap=suppress -->
@@ -1369,6 +1356,7 @@ const char *g_pcszIUnknown = "IUnknown";
<xsl:text>{</xsl:text>
<xsl:call-template name="emitNewline" />
<xsl:value-of select="' HRESULT rc = S_OK;'" />
+ <xsl:value-of select="concat(concat(' NOREF(', $G_responseElementVarName),');')" />
<xsl:call-template name="emitNewline" />
<xsl:call-template name="emitPrologue" />
diff --git a/src/VBox/Main/webservice/websrv-nsmap.xsl b/src/VBox/Main/webservice/websrv-nsmap.xsl
index c5158191d..d9524ea0d 100644
--- a/src/VBox/Main/webservice/websrv-nsmap.xsl
+++ b/src/VBox/Main/webservice/websrv-nsmap.xsl
@@ -9,15 +9,15 @@
See webservice/Makefile.kmk for an overview of all the things
generated for the webservice.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet
diff --git a/src/VBox/Main/webservice/websrv-php.xsl b/src/VBox/Main/webservice/websrv-php.xsl
index 5338a1eca..287735028 100644
--- a/src/VBox/Main/webservice/websrv-php.xsl
+++ b/src/VBox/Main/webservice/websrv-php.xsl
@@ -11,15 +11,15 @@
Contributed by James Lucas (mjlucas at eng.uts.edu.au).
- Copyright (C) 2008-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2008-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
diff --git a/src/VBox/Main/webservice/websrv-python.xsl b/src/VBox/Main/webservice/websrv-python.xsl
index 16affeb3b..d1dcff79d 100644
--- a/src/VBox/Main/webservice/websrv-python.xsl
+++ b/src/VBox/Main/webservice/websrv-python.xsl
@@ -9,15 +9,15 @@
VirtualBox.xidl. This Python file represents our
web service API. Depends on WSDL file for actual SOAP bindings.
- Copyright (C) 2008-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2008-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
diff --git a/src/VBox/Main/webservice/websrv-shared.inc.xsl b/src/VBox/Main/webservice/websrv-shared.inc.xsl
index 492d16f5d..b31eb72c1 100644
--- a/src/VBox/Main/webservice/websrv-shared.inc.xsl
+++ b/src/VBox/Main/webservice/websrv-shared.inc.xsl
@@ -6,15 +6,15 @@
See webservice/Makefile.kmk for an overview of all the things
generated for the webservice.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
@@ -150,12 +150,16 @@
<xsl:variable name="G_nameObjectRefEncoded"
select='"_USCOREthis"' />
-<!-- type to represent enums with in C++ COM callers -->
+<!-- type to represent enums within C++ COM callers -->
<xsl:variable name="G_funcPrefixInputEnumConverter"
select='"EnumSoap2Com_"' />
<xsl:variable name="G_funcPrefixOutputEnumConverter"
select='"EnumCom2Soap_"' />
+<!-- type to represent structs within C++ COM callers -->
+<xsl:variable name="G_funcPrefixOutputStructConverter"
+ select='"StructCom2Soap_"' />
+
<xsl:variable name="G_aSharedTypes">
<type idlname="octet" xmlname="unsignedByte" cname="unsigned char" gluename="BYTE" javaname="byte" />
<type idlname="boolean" xmlname="boolean" cname="bool" gluename="BOOL" javaname="Boolean" />
diff --git a/src/VBox/Main/webservice/websrv-typemap.xsl b/src/VBox/Main/webservice/websrv-typemap.xsl
index 8686a8abc..97efefa1e 100644
--- a/src/VBox/Main/webservice/websrv-typemap.xsl
+++ b/src/VBox/Main/webservice/websrv-typemap.xsl
@@ -8,15 +8,15 @@
See webservice/Makefile.kmk for an overview of all the things
generated for the webservice.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet
diff --git a/src/VBox/Main/webservice/websrv-wsdl-service.xsl b/src/VBox/Main/webservice/websrv-wsdl-service.xsl
index 0d720c0a6..e9d6e66c0 100644
--- a/src/VBox/Main/webservice/websrv-wsdl-service.xsl
+++ b/src/VBox/Main/webservice/websrv-wsdl-service.xsl
@@ -9,15 +9,15 @@
See webservice/Makefile.kmk for an overview of all the things
generated for the webservice.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet
diff --git a/src/VBox/Main/webservice/websrv-wsdl.xsl b/src/VBox/Main/webservice/websrv-wsdl.xsl
index c26db925a..2791c3b86 100644
--- a/src/VBox/Main/webservice/websrv-wsdl.xsl
+++ b/src/VBox/Main/webservice/websrv-wsdl.xsl
@@ -9,15 +9,15 @@
See webservice/Makefile.kmk for an overview of all the things
generated for the webservice.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<!--
@@ -93,6 +93,7 @@
targetNamespace="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:vbox="http://www.virtualbox.org/"
xmlns:exsl="http://exslt.org/common"
@@ -460,7 +461,7 @@
<xsl:param name="_params" />
<xsl:param name="_valuetype" /> <!-- optional, for attribute setter messages -->
- <message>
+ <wsdl:message>
<xsl:attribute name="name"><xsl:value-of select="concat($_ifname, $G_classSeparator, $_methodname, $G_methodRequest)" /></xsl:attribute>
<xsl:call-template name="convertTypeAndEmitPartOrElement">
@@ -469,10 +470,10 @@
<xsl:with-param name="name" select="'parameters'" />
<xsl:with-param name="type" select="$G_typeIsGlobalRequestElementMarker" />
<xsl:with-param name="safearray" select="'no'" />
- <xsl:with-param name="elname" select="'part'" /> <!-- "part" or "element" -->
+ <xsl:with-param name="elname" select="'wsdl:part'" /> <!-- "part" or "element" -->
<xsl:with-param name="attrname" select="'element'" /> <!-- attrib of part of element: <part type=...> or <part element=...> or <element type=...> -->
</xsl:call-template>
- </message>
+ </wsdl:message>
</xsl:template>
<!--
@@ -485,7 +486,7 @@
<xsl:param name="_params" /> <!-- set of parameter elements -->
<xsl:param name="_resulttype" /> <!-- for attribute getter methods only -->
- <message>
+ <wsdl:message>
<xsl:attribute name="name"><xsl:copy-of select="$_ifname" /><xsl:value-of select="$G_classSeparator" /><xsl:value-of select="$_methodname" /><xsl:copy-of select="$G_methodResponse" /></xsl:attribute>
<!-- <xsl:variable name="cOutParams" select="count($_params[@dir='out']) + count($_params[@dir='return'])" /> -->
@@ -495,10 +496,10 @@
<xsl:with-param name="name" select="'parameters'" />
<xsl:with-param name="type" select="$G_typeIsGlobalResponseElementMarker" />
<xsl:with-param name="safearray" select="'no'" />
- <xsl:with-param name="elname" select="'part'" /> <!-- "part" or "element" -->
+ <xsl:with-param name="elname" select="'wsdl:part'" /> <!-- "part" or "element" -->
<xsl:with-param name="attrname" select="'element'" /> <!-- attrib of part of element: <part type=...> or <part element=...> or <element type=...> -->
</xsl:call-template>
- </message>
+ </wsdl:message>
</xsl:template>
<!--
@@ -543,13 +544,13 @@
<xsl:with-param name="_methodname" select="$attrSetter" />
<xsl:with-param name="_params" select="/.." /> <!-- empty set -->
<xsl:with-param name="_valuetype" select="$attrtype" />
- <xsl:with-param name="elname" select="'part'" /> <!-- "part" or "element" -->
+ <xsl:with-param name="elname" select="'wsdl:part'" /> <!-- "part" or "element" -->
</xsl:call-template>
<xsl:call-template name="emitResultMessage">
<xsl:with-param name="_ifname" select="$ifname" />
<xsl:with-param name="_methodname" select="$attrSetter" />
<xsl:with-param name="_params" select="/.." /> <!-- empty set -->
- <xsl:with-param name="elname" select="'part'" /> <!-- "part" or "element" -->
+ <xsl:with-param name="elname" select="'wsdl:part'" /> <!-- "part" or "element" -->
</xsl:call-template>
</xsl:template>
@@ -566,7 +567,7 @@
<xsl:call-template name="debugMsg"><xsl:with-param name="msg" select="concat('....emitInOutOperation ', $_ifname, '::', $_methodname)" /></xsl:call-template>
- <operation>
+ <wsdl:operation>
<xsl:attribute name="name">
<xsl:value-of select="concat($_ifname, '_', $_methodname)" />
</xsl:attribute>
@@ -577,7 +578,7 @@
<xsl:attribute name="style"><xsl:value-of select="$G_basefmt" /></xsl:attribute>
</soap:operation>
</xsl:if>
- <input>
+ <wsdl:input>
<xsl:choose>
<xsl:when test="$_fSoap">
<soap:body>
@@ -589,10 +590,10 @@
<xsl:attribute name="message">vbox:<xsl:copy-of select="$_ifname" /><xsl:value-of select="$G_classSeparator" /><xsl:value-of select="$_methodname" /><xsl:copy-of select="$G_methodRequest" /></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
- </input>
+ </wsdl:input>
<xsl:choose>
<xsl:when test="$_resulttype">
- <output>
+ <wsdl:output>
<xsl:choose>
<xsl:when test="$_fSoap">
<soap:body>
@@ -604,11 +605,11 @@
<xsl:attribute name="message">vbox:<xsl:copy-of select="$_ifname" /><xsl:value-of select="$G_classSeparator" /><xsl:value-of select="$_methodname" /><xsl:copy-of select="$G_methodResponse" /></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
- </output>
+ </wsdl:output>
</xsl:when>
<xsl:otherwise>
<!-- <xsl:if test="count($_params[@dir='out'] | $_params[@dir='return']) > 0"> -->
- <output>
+ <wsdl:output>
<xsl:choose>
<xsl:when test="$_fSoap">
<soap:body>
@@ -620,29 +621,29 @@
<xsl:attribute name="message">vbox:<xsl:copy-of select="$_ifname" /><xsl:value-of select="$G_classSeparator" /><xsl:value-of select="$_methodname" /><xsl:copy-of select="$G_methodResponse" /></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
- </output>
+ </wsdl:output>
<!-- </xsl:if> -->
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="not($_fSoap)">
- <fault name="InvalidObjectFault" message="vbox:InvalidObjectFaultMsg" />
- <fault name="RuntimeFault" message="vbox:RuntimeFaultMsg" />
+ <wsdl:fault name="InvalidObjectFault" message="vbox:InvalidObjectFaultMsg" />
+ <wsdl:fault name="RuntimeFault" message="vbox:RuntimeFaultMsg" />
</xsl:when>
<xsl:otherwise>
- <fault name="InvalidObjectFault">
+ <wsdl:fault name="InvalidObjectFault">
<soap:fault name="InvalidObjectFault">
<xsl:attribute name="use"><xsl:value-of select="$G_parmfmt" /></xsl:attribute>
</soap:fault>
- </fault>
- <fault name="RuntimeFault">
+ </wsdl:fault>
+ <wsdl:fault name="RuntimeFault">
<soap:fault name="RuntimeFault">
<xsl:attribute name="use"><xsl:value-of select="$G_parmfmt" /></xsl:attribute>
</soap:fault>
- </fault>
+ </wsdl:fault>
</xsl:otherwise>
</xsl:choose>
- </operation>
+ </wsdl:operation>
</xsl:template>
<!--
@@ -742,7 +743,7 @@
<xsl:with-param name="_wsmap" select="$wsmap" />
<xsl:with-param name="_methodname" select="$methodname" />
<xsl:with-param name="_params" select="param" />
- <xsl:with-param name="elname" select="'part'" /> <!-- "part" or "element" -->
+ <xsl:with-param name="elname" select="'wsdl:part'" /> <!-- "part" or "element" -->
</xsl:call-template>
<!-- emit a second "result" message only if the method has "out" arguments or a return value -->
<!-- <xsl:if test="(count(param[@dir='out'] | param[@dir='return']) > 0)"> -->
@@ -751,7 +752,7 @@
<xsl:with-param name="_wsmap" select="$wsmap" />
<xsl:with-param name="_methodname" select="@name" />
<xsl:with-param name="_params" select="param" />
- <xsl:with-param name="elname" select="'part'" /> <!-- "part" or "element" -->
+ <xsl:with-param name="elname" select="'wsdl:part'" /> <!-- "part" or "element" -->
</xsl:call-template>
<!-- </xsl:if> -->
</xsl:otherwise>
@@ -956,10 +957,9 @@
and emit complexTypes for all method arguments and return values.
-->
<xsl:template match="library">
- <definitions
+ <wsdl:definitions
name="VirtualBox"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
- <xsl:attribute name="xmlns">http://schemas.xmlsoap.org/wsdl/</xsl:attribute>
<xsl:attribute name="targetNamespace"><xsl:value-of select="$G_targetNamespace" /></xsl:attribute>
<!-- at top of WSDL file, dump a <types> section with user-defined types -->
<xsl:comment>
@@ -969,7 +969,7 @@
*
******************************************************
</xsl:comment>
- <types>
+ <wsdl:types>
<xsd:schema>
<xsl:attribute name="targetNamespace"><xsl:value-of select='$G_targetNamespace' /></xsl:attribute>
@@ -1193,14 +1193,14 @@
</xsd:schema>
- </types>
+ </wsdl:types>
- <message name="InvalidObjectFaultMsg">
- <part name="fault" element="vbox:InvalidObjectFault" />
- </message>
- <message name="RuntimeFaultMsg">
- <part name="fault" element="vbox:RuntimeFault" />
- </message>
+ <wsdl:message name="InvalidObjectFaultMsg">
+ <wsdl:part name="fault" element="vbox:InvalidObjectFault" />
+ </wsdl:message>
+ <wsdl:message name="RuntimeFaultMsg">
+ <wsdl:part name="fault" element="vbox:RuntimeFault" />
+ </wsdl:message>
<xsl:comment>
******************************************************
@@ -1241,7 +1241,7 @@
******************************************************
</xsl:comment>
- <portType>
+ <wsdl:portType>
<xsl:attribute name="name"><xsl:copy-of select="'vbox'" /><xsl:value-of select="$G_portTypeSuffix" /></xsl:attribute>
<xsl:for-each select="//interface">
@@ -1261,7 +1261,7 @@
</xsl:call-template>
</xsl:if>
</xsl:for-each>
- </portType>
+ </wsdl:portType>
<xsl:comment>
******************************************************
@@ -1271,7 +1271,7 @@
******************************************************
</xsl:comment>
- <binding>
+ <wsdl:binding>
<xsl:attribute name="name"><xsl:value-of select="concat('vbox', $G_bindingSuffix)" /></xsl:attribute>
<xsl:attribute name="type"><xsl:value-of select="concat('vbox:vbox', $G_portTypeSuffix)" /></xsl:attribute>
@@ -1297,9 +1297,9 @@
</xsl:call-template>
</xsl:if>
</xsl:for-each>
- </binding>
+ </wsdl:binding>
- </definitions>
+ </wsdl:definitions>
</xsl:template>
diff --git a/src/VBox/Main/webservice/websrv-wsdl2gsoapH.xsl b/src/VBox/Main/webservice/websrv-wsdl2gsoapH.xsl
index 1abedbfa2..d40ba83c7 100644
--- a/src/VBox/Main/webservice/websrv-wsdl2gsoapH.xsl
+++ b/src/VBox/Main/webservice/websrv-wsdl2gsoapH.xsl
@@ -9,15 +9,15 @@
See webservice/Makefile.kmk for an overview of all the things
generated for the webservice.
- Copyright (C) 2006-2010 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2010 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet
diff --git a/src/VBox/Main/xml/SchemaDefs.xsl b/src/VBox/Main/xml/SchemaDefs.xsl
index c39efd87b..3d91dea85 100644
--- a/src/VBox/Main/xml/SchemaDefs.xsl
+++ b/src/VBox/Main/xml/SchemaDefs.xsl
@@ -8,15 +8,15 @@
* This template depends on XML Schema structure (type names and constraints)
* and should be reviewed on every Schema change.
- Copyright (C) 2006-2008 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2011 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet version="1.0"
@@ -171,12 +171,6 @@ namespace SchemaDefs
xsd:complexType[@name='TDisplay']/xsd:attribute[@name='monitorCount']//xsd:maxInclusive/@value
"/>
</xsl:call-template>
- <xsl:call-template name="defineEnumMember">
- <xsl:with-param name="member" select="' NetworkAdapterCount'"/>
- <xsl:with-param name="select" select="
- xsd:complexType[@name='TNetworkAdapter']/xsd:attribute[@name='slot']//xsd:maxExclusive/@value
- "/>
- </xsl:call-template>
<xsl:call-template name="defineEnumMember">
<xsl:with-param name="member" select="' SerialPortCount'"/>
@@ -202,33 +196,6 @@ namespace SchemaDefs
</xsl:template>
<!--
- * aliases (defines) for individual OSTypeIds array elements
--->
-<xsl:template match="xsd:schema" mode="declare">
-
- <xsl:text>&#x0A; extern const char *OSTypeIds[];&#x0A;</xsl:text>
-
- <xsl:text>&#x0A; enum { OSTypeId_COUNT = </xsl:text>
- <xsl:value-of select="count (
- xsd:simpleType[@name='TGuestOSType']/xsd:restriction[@base='xsd:string']/xsd:enumeration |
- document(xsd:include[not(@schemaLocation='VirtualBox-settings-root.xsd')]/@schemaLocation)/xsd:schema/xsd:simpleType[@name='TGuestOSType']/xsd:restriction[@base='xsd:string']/xsd:enumeration
- )"/>
- <xsl:text> };&#x0A;&#x0A;</xsl:text>
-
- <xsl:for-each select="
- xsd:simpleType[@name='TGuestOSType']/xsd:restriction[@base='xsd:string']/xsd:enumeration |
- document(xsd:include[not(@schemaLocation='VirtualBox-settings-root.xsd')]/@schemaLocation)/xsd:schema/xsd:simpleType[@name='TGuestOSType']/xsd:restriction[@base='xsd:string']/xsd:enumeration
- ">
- <xsl:text> #define SchemaDefs_OSTypeId_</xsl:text>
- <xsl:value-of select="@value"/>
- <xsl:text> SchemaDefs::OSTypeIds [</xsl:text>
- <xsl:value-of select="position()-1"/>
- <xsl:text>]&#x0A;</xsl:text>
- </xsl:for-each>
-
-</xsl:template>
-
-<!--
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* define mode (C++ source file)
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -256,26 +223,6 @@ namespace SchemaDefs
</xsl:template>
<!--
- * array of OSTypeIds
--->
-<xsl:template match="xsd:schema" mode="define">
- <xsl:text> const char *OSTypeIds[] =
- {
-</xsl:text>
- <xsl:for-each select="
- xsd:simpleType[@name='TGuestOSType']/xsd:restriction[@base='xsd:string']/xsd:enumeration |
- document(xsd:include[not(@schemaLocation='VirtualBox-settings-root.xsd')]/@schemaLocation)/xsd:schema/xsd:simpleType[@name='TGuestOSType']/xsd:restriction[@base='xsd:string']/xsd:enumeration
- ">
- <xsl:text> "</xsl:text>
- <xsl:value-of select="@value"/>
- <xsl:text>",
-</xsl:text>
- </xsl:for-each>
- <xsl:text> };
-</xsl:text>
-</xsl:template>
-
-<!--
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* END
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/VBox/Main/xml/Settings.cpp b/src/VBox/Main/xml/Settings.cpp
index 8448ffb56..8cb1e1269 100644
--- a/src/VBox/Main/xml/Settings.cpp
+++ b/src/VBox/Main/xml/Settings.cpp
@@ -16,6 +16,9 @@
* highest value to see which code in here needs adjusting.
*
* Certainly ConfigFileBase::ConfigFileBase() will. Change VBOX_XML_VERSION below as well.
+ * VBOX_XML_VERSION does not have to be changed if the settings for a default VM do not
+ * touch newly introduced attributes or tags. It has the benefit that older VirtualBox
+ * versions do not trigger their "newer" code path.
*
* Once a new settings version has been added, these are the rules for introducing a new
* setting: If an XML element or attribute or value is introduced that was not present in
@@ -51,7 +54,7 @@
*/
/*
- * Copyright (C) 2007-2011 Oracle Corporation
+ * Copyright (C) 2007-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -76,6 +79,7 @@
#include "SchemaDefs.h"
#include "Logging.h"
+#include "HashedPw.h"
using namespace com;
using namespace settings;
@@ -321,7 +325,9 @@ ConfigFileBase::ConfigFileBase(const com::Utf8Str *pstrFilename)
m->sv = SettingsVersion_v1_11;
else if (ulMinor == 12)
m->sv = SettingsVersion_v1_12;
- else if (ulMinor > 12)
+ else if (ulMinor == 13)
+ m->sv = SettingsVersion_v1_13;
+ else if (ulMinor > 13)
m->sv = SettingsVersion_Future;
}
else if (ulMajor > 1)
@@ -832,11 +838,15 @@ void ConfigFileBase::setVersionAttribute(xml::ElementNode &elm)
pcszVersion = "1.12";
break;
+ case SettingsVersion_v1_13:
+ pcszVersion = "1.13";
+ break;
+
case SettingsVersion_Future:
// can be set if this code runs on XML files that were created by a future version of VBox;
// in that case, downgrade to current version when writing since we can't write future versions...
- pcszVersion = "1.12";
- m->sv = SettingsVersion_v1_12;
+ pcszVersion = "1.13";
+ m->sv = SettingsVersion_v1_13;
break;
default:
@@ -1283,6 +1293,7 @@ MainConfigFile::MainConfigFile(const Utf8Str *pstrFilename)
pelmGlobalChild->getAttributeValue("webServiceAuthLibrary", systemProperties.strWebServiceAuthLibrary);
pelmGlobalChild->getAttributeValue("defaultVRDEExtPack", systemProperties.strDefaultVRDEExtPack);
pelmGlobalChild->getAttributeValue("LogHistoryCount", systemProperties.ulLogHistoryCount);
+ pelmGlobalChild->getAttributeValue("autostartDatabasePath", systemProperties.strAutostartDatabasePath);
}
else if (pelmGlobalChild->nameEquals("ExtraData"))
readExtraData(*pelmGlobalChild, mapExtraDataItems);
@@ -1393,6 +1404,8 @@ void MainConfigFile::write(const com::Utf8Str strFilename)
if (systemProperties.strDefaultVRDEExtPack.length())
pelmSysProps->setAttribute("defaultVRDEExtPack", systemProperties.strDefaultVRDEExtPack);
pelmSysProps->setAttribute("LogHistoryCount", systemProperties.ulLogHistoryCount);
+ if (systemProperties.strAutostartDatabasePath.length())
+ pelmSysProps->setAttribute("autostartDatabasePath", systemProperties.strAutostartDatabasePath);
buildUSBDeviceFilters(*pelmGlobal->createChild("USBDeviceFilters"),
host.llUSBDeviceFilters,
@@ -1493,6 +1506,7 @@ bool NetworkAdapter::operator==(const NetworkAdapter &n) const
&& (strGenericDriver == n.strGenericDriver)
&& (genericProperties == n.genericProperties)
&& (ulBootPriority == n.ulBootPriority)
+ && (strBandwidthGroup == n.strBandwidthGroup)
)
);
}
@@ -1574,9 +1588,6 @@ bool GuestProperty::operator==(const GuestProperty &g) const
#define HWVIRTEXCLUSIVEDEFAULT true
#endif
-/**
- * Hardware struct constructor.
- */
Hardware::Hardware()
: strVersion("1"),
fHardwareVirt(true),
@@ -1588,19 +1599,24 @@ Hardware::Hardware()
fPAE(false),
cCPUs(1),
fCpuHotPlug(false),
- fHpetEnabled(false),
+ fHPETEnabled(false),
ulCpuExecutionCap(100),
ulMemorySizeMB((uint32_t)-1),
ulVRAMSizeMB(8),
cMonitors(1),
fAccelerate3D(false),
fAccelerate2DVideo(false),
+ ulVideoCaptureHorzRes(640),
+ ulVideoCaptureVertRes(480),
+ fVideoCaptureEnabled(false),
+ strVideoCaptureFile("Test.webm"),
firmwareType(FirmwareType_BIOS),
- pointingHidType(PointingHidType_PS2Mouse),
- keyboardHidType(KeyboardHidType_PS2Keyboard),
+ pointingHIDType(PointingHIDType_PS2Mouse),
+ keyboardHIDType(KeyboardHIDType_PS2Keyboard),
chipsetType(ChipsetType_PIIX3),
fEmulatedUSBCardReader(false),
- clipboardMode(ClipboardMode_Bidirectional),
+ clipboardMode(ClipboardMode_Disabled),
+ dragAndDropMode(DragAndDropMode_Disabled),
ulMemoryBalloonSize(0),
fPageFusionEnabled(false)
{
@@ -1649,7 +1665,7 @@ bool Hardware::operator==(const Hardware& h) const
&& (cCPUs == h.cCPUs)
&& (fCpuHotPlug == h.fCpuHotPlug)
&& (ulCpuExecutionCap == h.ulCpuExecutionCap)
- && (fHpetEnabled == h.fHpetEnabled)
+ && (fHPETEnabled == h.fHPETEnabled)
&& (llCpus == h.llCpus)
&& (llCpuIdLeafs == h.llCpuIdLeafs)
&& (ulMemorySizeMB == h.ulMemorySizeMB)
@@ -1658,9 +1674,13 @@ bool Hardware::operator==(const Hardware& h) const
&& (cMonitors == h.cMonitors)
&& (fAccelerate3D == h.fAccelerate3D)
&& (fAccelerate2DVideo == h.fAccelerate2DVideo)
+ && (fVideoCaptureEnabled == h.fVideoCaptureEnabled)
+ && (strVideoCaptureFile == h.strVideoCaptureFile)
+ && (ulVideoCaptureHorzRes == h.ulVideoCaptureHorzRes)
+ && (ulVideoCaptureVertRes == h.ulVideoCaptureVertRes)
&& (firmwareType == h.firmwareType)
- && (pointingHidType == h.pointingHidType)
- && (keyboardHidType == h.keyboardHidType)
+ && (pointingHIDType == h.pointingHIDType)
+ && (keyboardHIDType == h.keyboardHIDType)
&& (chipsetType == h.chipsetType)
&& (fEmulatedUSBCardReader == h.fEmulatedUSBCardReader)
&& (vrdeSettings == h.vrdeSettings)
@@ -1672,6 +1692,7 @@ bool Hardware::operator==(const Hardware& h) const
&& (audioAdapter == h.audioAdapter)
&& (llSharedFolders == h.llSharedFolders)
&& (clipboardMode == h.clipboardMode)
+ && (dragAndDropMode == h.dragAndDropMode)
&& (ulMemoryBalloonSize == h.ulMemoryBalloonSize)
&& (fPageFusionEnabled == h.fPageFusionEnabled)
&& (llGuestProperties == h.llGuestProperties)
@@ -1694,6 +1715,7 @@ bool AttachedDevice::operator==(const AttachedDevice &a) const
&& (fPassThrough == a.fPassThrough)
&& (fTempEject == a.fTempEject)
&& (fNonRotational == a.fNonRotational)
+ && (fDiscard == a.fDiscard)
&& (lPort == a.lPort)
&& (lDevice == a.lDevice)
&& (uuid == a.uuid)
@@ -1754,17 +1776,19 @@ bool Snapshot::operator==(const Snapshot &s) const
&& (hardware == s.hardware) // deep compare
&& (storage == s.storage) // deep compare
&& (llChildSnapshots == s.llChildSnapshots) // deep compare
+ && debugging == s.debugging
+ && autostart == s.autostart
)
);
}
/**
- * IoSettings constructor.
+ * IOSettings constructor.
*/
-IoSettings::IoSettings()
+IOSettings::IOSettings()
{
- fIoCacheEnabled = true;
- ulIoCacheSize = 5;
+ fIOCacheEnabled = true;
+ ulIOCacheSize = 5;
}
////////////////////////////////////////////////////////////////////////////////
@@ -2027,9 +2051,9 @@ void MachineConfigFile::readAttachedNetworkMode(const xml::ElementNode &elmMode,
const xml::ElementNode *pelmDNS;
if ((pelmDNS = elmMode.findChildElement("DNS")))
{
- pelmDNS->getAttributeValue("pass-domain", nic.nat.fDnsPassDomain);
- pelmDNS->getAttributeValue("use-proxy", nic.nat.fDnsProxy);
- pelmDNS->getAttributeValue("use-host-resolver", nic.nat.fDnsUseHostResolver);
+ pelmDNS->getAttributeValue("pass-domain", nic.nat.fDNSPassDomain);
+ pelmDNS->getAttributeValue("use-proxy", nic.nat.fDNSProxy);
+ pelmDNS->getAttributeValue("use-host-resolver", nic.nat.fDNSUseHostResolver);
}
const xml::ElementNode *pelmAlias;
if ((pelmAlias = elmMode.findChildElement("Alias")))
@@ -2041,9 +2065,9 @@ void MachineConfigFile::readAttachedNetworkMode(const xml::ElementNode &elmMode,
const xml::ElementNode *pelmTFTP;
if ((pelmTFTP = elmMode.findChildElement("TFTP")))
{
- pelmTFTP->getAttributeValue("prefix", nic.nat.strTftpPrefix);
- pelmTFTP->getAttributeValue("boot-file", nic.nat.strTftpBootFile);
- pelmTFTP->getAttributeValue("next-server", nic.nat.strTftpNextServer);
+ pelmTFTP->getAttributeValue("prefix", nic.nat.strTFTPPrefix);
+ pelmTFTP->getAttributeValue("boot-file", nic.nat.strTFTPBootFile);
+ pelmTFTP->getAttributeValue("next-server", nic.nat.strTFTPNextServer);
}
xml::ElementNodesList plstNatPF;
elmMode.getChildElements(plstNatPF, "Forwarding");
@@ -2425,40 +2449,40 @@ void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
}
else if (pelmHwChild->nameEquals("HID"))
{
- Utf8Str strHidType;
- if (pelmHwChild->getAttributeValue("Keyboard", strHidType))
+ Utf8Str strHIDType;
+ if (pelmHwChild->getAttributeValue("Keyboard", strHIDType))
{
- if (strHidType == "None")
- hw.keyboardHidType = KeyboardHidType_None;
- else if (strHidType == "USBKeyboard")
- hw.keyboardHidType = KeyboardHidType_USBKeyboard;
- else if (strHidType == "PS2Keyboard")
- hw.keyboardHidType = KeyboardHidType_PS2Keyboard;
- else if (strHidType == "ComboKeyboard")
- hw.keyboardHidType = KeyboardHidType_ComboKeyboard;
+ if (strHIDType == "None")
+ hw.keyboardHIDType = KeyboardHIDType_None;
+ else if (strHIDType == "USBKeyboard")
+ hw.keyboardHIDType = KeyboardHIDType_USBKeyboard;
+ else if (strHIDType == "PS2Keyboard")
+ hw.keyboardHIDType = KeyboardHIDType_PS2Keyboard;
+ else if (strHIDType == "ComboKeyboard")
+ hw.keyboardHIDType = KeyboardHIDType_ComboKeyboard;
else
throw ConfigFileError(this,
pelmHwChild,
N_("Invalid value '%s' in HID/Keyboard/@type"),
- strHidType.c_str());
+ strHIDType.c_str());
}
- if (pelmHwChild->getAttributeValue("Pointing", strHidType))
+ if (pelmHwChild->getAttributeValue("Pointing", strHIDType))
{
- if (strHidType == "None")
- hw.pointingHidType = PointingHidType_None;
- else if (strHidType == "USBMouse")
- hw.pointingHidType = PointingHidType_USBMouse;
- else if (strHidType == "USBTablet")
- hw.pointingHidType = PointingHidType_USBTablet;
- else if (strHidType == "PS2Mouse")
- hw.pointingHidType = PointingHidType_PS2Mouse;
- else if (strHidType == "ComboMouse")
- hw.pointingHidType = PointingHidType_ComboMouse;
+ if (strHIDType == "None")
+ hw.pointingHIDType = PointingHIDType_None;
+ else if (strHIDType == "USBMouse")
+ hw.pointingHIDType = PointingHIDType_USBMouse;
+ else if (strHIDType == "USBTablet")
+ hw.pointingHIDType = PointingHIDType_USBTablet;
+ else if (strHIDType == "PS2Mouse")
+ hw.pointingHIDType = PointingHIDType_PS2Mouse;
+ else if (strHIDType == "ComboMouse")
+ hw.pointingHIDType = PointingHIDType_ComboMouse;
else
throw ConfigFileError(this,
pelmHwChild,
N_("Invalid value '%s' in HID/Pointing/@type"),
- strHidType.c_str());
+ strHIDType.c_str());
}
}
else if (pelmHwChild->nameEquals("Chipset"))
@@ -2479,7 +2503,7 @@ void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
}
else if (pelmHwChild->nameEquals("HPET"))
{
- pelmHwChild->getAttributeValue("enabled", hw.fHpetEnabled);
+ pelmHwChild->getAttributeValue("enabled", hw.fHPETEnabled);
}
else if (pelmHwChild->nameEquals("Boot"))
{
@@ -2536,6 +2560,14 @@ void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
pelmHwChild->getAttributeValue("Accelerate3D", hw.fAccelerate3D); // pre-v1.5 variant
pelmHwChild->getAttributeValue("accelerate2DVideo", hw.fAccelerate2DVideo);
}
+ else if (pelmHwChild->nameEquals("VideoRecording"))
+ {
+ pelmHwChild->getAttributeValue("enabled", hw.fVideoCaptureEnabled);
+ pelmHwChild->getAttributeValue("file", hw.strVideoCaptureFile);
+ pelmHwChild->getAttributeValue("horzRes", hw.ulVideoCaptureHorzRes);
+ pelmHwChild->getAttributeValue("vertRes", hw.ulVideoCaptureVertRes);
+ }
+
else if (pelmHwChild->nameEquals("RemoteDisplay"))
{
pelmHwChild->getAttributeValue("enabled", hw.vrdeSettings.fEnabled);
@@ -2746,6 +2778,23 @@ void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in Clipboard/@mode attribute"), strTemp.c_str());
}
}
+ else if (pelmHwChild->nameEquals("DragAndDrop"))
+ {
+ Utf8Str strTemp;
+ if (pelmHwChild->getAttributeValue("mode", strTemp))
+ {
+ if (strTemp == "Disabled")
+ hw.dragAndDropMode = DragAndDropMode_Disabled;
+ else if (strTemp == "HostToGuest")
+ hw.dragAndDropMode = DragAndDropMode_HostToGuest;
+ else if (strTemp == "GuestToHost")
+ hw.dragAndDropMode = DragAndDropMode_GuestToHost;
+ else if (strTemp == "Bidirectional")
+ hw.dragAndDropMode = DragAndDropMode_Bidirectional;
+ else
+ throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in DragAndDrop/@mode attribute"), strTemp.c_str());
+ }
+ }
else if (pelmHwChild->nameEquals("Guest"))
{
if (!pelmHwChild->getAttributeValue("memoryBalloonSize", hw.ulMemoryBalloonSize))
@@ -2756,12 +2805,12 @@ void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
else if (pelmHwChild->nameEquals("IO"))
{
const xml::ElementNode *pelmBwGroups;
- const xml::ElementNode *pelmIoChild;
+ const xml::ElementNode *pelmIOChild;
- if ((pelmIoChild = pelmHwChild->findChildElement("IoCache")))
+ if ((pelmIOChild = pelmHwChild->findChildElement("IoCache")))
{
- pelmIoChild->getAttributeValue("enabled", hw.ioSettings.fIoCacheEnabled);
- pelmIoChild->getAttributeValue("size", hw.ioSettings.ulIoCacheSize);
+ pelmIOChild->getAttributeValue("enabled", hw.ioSettings.fIOCacheEnabled);
+ pelmIOChild->getAttributeValue("size", hw.ioSettings.ulIOCacheSize);
}
if ((pelmBwGroups = pelmHwChild->findChildElement("BandwidthGroups")))
@@ -2787,7 +2836,11 @@ void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
else
throw ConfigFileError(this, pelmBandwidthGroup, N_("Missing BandwidthGroup/@type attribute"));
- pelmBandwidthGroup->getAttributeValue("maxMbPerSec", gr.cMaxMbPerSec);
+ if (!pelmBandwidthGroup->getAttributeValue("maxBytesPerSec", gr.cMaxBytesPerSec))
+ {
+ pelmBandwidthGroup->getAttributeValue("maxMbPerSec", gr.cMaxBytesPerSec);
+ gr.cMaxBytesPerSec *= _1M;
+ }
hw.ioSettings.llBandwidthGroups.push_back(gr);
}
}
@@ -2800,7 +2853,7 @@ void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
const xml::ElementNode *pelmDevice;
while ((pelmDevice = nl2.forAllNodes()))
{
- HostPciDeviceAttachment hpda;
+ HostPCIDeviceAttachment hpda;
if (!pelmDevice->getAttributeValue("host", hpda.uHostAddress))
throw ConfigFileError(this, pelmDevice, N_("Missing Device/@host attribute"));
@@ -2995,10 +3048,14 @@ void MachineConfigFile::readStorageControllers(const xml::ElementNode &elmStorag
Utf8Str strTemp;
pelmAttached->getAttributeValue("type", strTemp);
+ att.fDiscard = false;
+ att.fNonRotational = false;
+
if (strTemp == "HardDisk")
{
att.deviceType = DeviceType_HardDisk;
pelmAttached->getAttributeValue("nonrotational", att.fNonRotational);
+ pelmAttached->getAttributeValue("discard", att.fDiscard);
}
else if (m->sv >= SettingsVersion_v1_9)
{
@@ -3148,6 +3205,90 @@ void MachineConfigFile::readDVDAndFloppies_pre1_9(const xml::ElementNode &elmHar
}
/**
+ * Called for reading the <Teleporter> element under <Machine>.
+ */
+void MachineConfigFile::readTeleporter(const xml::ElementNode *pElmTeleporter,
+ MachineUserData *pUserData)
+{
+ pElmTeleporter->getAttributeValue("enabled", pUserData->fTeleporterEnabled);
+ pElmTeleporter->getAttributeValue("port", pUserData->uTeleporterPort);
+ pElmTeleporter->getAttributeValue("address", pUserData->strTeleporterAddress);
+ pElmTeleporter->getAttributeValue("password", pUserData->strTeleporterPassword);
+
+ if ( pUserData->strTeleporterPassword.isNotEmpty()
+ && !VBoxIsPasswordHashed(&pUserData->strTeleporterPassword))
+ VBoxHashPassword(&pUserData->strTeleporterPassword);
+}
+
+/**
+ * Called for reading the <Debugging> element under <Machine> or <Snapshot>.
+ */
+void MachineConfigFile::readDebugging(const xml::ElementNode *pElmDebugging, Debugging *pDbg)
+{
+ if (!pElmDebugging || m->sv < SettingsVersion_v1_13)
+ return;
+
+ const xml::ElementNode * const pelmTracing = pElmDebugging->findChildElement("Tracing");
+ if (pelmTracing)
+ {
+ pelmTracing->getAttributeValue("enabled", pDbg->fTracingEnabled);
+ pelmTracing->getAttributeValue("allowTracingToAccessVM", pDbg->fAllowTracingToAccessVM);
+ pelmTracing->getAttributeValue("config", pDbg->strTracingConfig);
+ }
+}
+
+/**
+ * Called for reading the <Autostart> element under <Machine> or <Snapshot>.
+ */
+void MachineConfigFile::readAutostart(const xml::ElementNode *pElmAutostart, Autostart *pAutostart)
+{
+ Utf8Str strAutostop;
+
+ if (!pElmAutostart || m->sv < SettingsVersion_v1_13)
+ return;
+
+ pElmAutostart->getAttributeValue("enabled", pAutostart->fAutostartEnabled);
+ pElmAutostart->getAttributeValue("delay", pAutostart->uAutostartDelay);
+ pElmAutostart->getAttributeValue("autostop", strAutostop);
+ if (strAutostop == "Disabled")
+ pAutostart->enmAutostopType = AutostopType_Disabled;
+ else if (strAutostop == "SaveState")
+ pAutostart->enmAutostopType = AutostopType_SaveState;
+ else if (strAutostop == "PowerOff")
+ pAutostart->enmAutostopType = AutostopType_PowerOff;
+ else if (strAutostop == "AcpiShutdown")
+ pAutostart->enmAutostopType = AutostopType_AcpiShutdown;
+ else
+ throw ConfigFileError(this, pElmAutostart, N_("Invalid value '%s' for Autostart/@autostop attribute"), strAutostop.c_str());
+}
+
+/**
+ * Called for reading the <Groups> element under <Machine>.
+ */
+void MachineConfigFile::readGroups(const xml::ElementNode *pElmGroups, StringsList *pllGroups)
+{
+ pllGroups->clear();
+ if (!pElmGroups || m->sv < SettingsVersion_v1_13)
+ {
+ pllGroups->push_back("/");
+ return;
+ }
+
+ xml::NodesLoop nlGroups(*pElmGroups);
+ const xml::ElementNode *pelmGroup;
+ while ((pelmGroup = nlGroups.forAllNodes()))
+ {
+ if (pelmGroup->nameEquals("Group"))
+ {
+ Utf8Str strGroup;
+ if (!pelmGroup->getAttributeValue("name", strGroup))
+ throw ConfigFileError(this, pelmGroup, N_("Required Group/@name attribute is missing"));
+ pllGroups->push_back(strGroup);
+ }
+ }
+}
+
+/**
* Called initially for the <Snapshot> element under <Machine>, if present,
* to store the snapshot's data into the given Snapshot structure (which is
* then the one in the Machine struct). This might then recurse if
@@ -3219,6 +3360,10 @@ void MachineConfigFile::readSnapshot(const xml::ElementNode &elmSnapshot,
// go through Hardware once more to repair the settings controller structures
// with data from old DVDDrive and FloppyDrive elements
readDVDAndFloppies_pre1_9(*pelmHardware, snap.storage);
+
+ readDebugging(elmSnapshot.findChildElement("Debugging"), &snap.debugging);
+ readAutostart(elmSnapshot.findChildElement("Autostart"), &snap.autostart);
+ // note: Groups exist only for Machine, not for Snapshot
}
const struct {
@@ -3291,6 +3436,7 @@ void MachineConfigFile::readMachine(const xml::ElementNode &elmMachine)
{
parseUUID(uuid, strUUID);
+ elmMachine.getAttributeValue("directoryIncludesUUID", machineUserData.fDirectoryIncludesUUID);
elmMachine.getAttributeValue("nameSync", machineUserData.fNameSync);
Utf8Str str;
@@ -3346,12 +3492,7 @@ void MachineConfigFile::readMachine(const xml::ElementNode &elmMachine)
else if (pelmMachineChild->nameEquals("Description"))
machineUserData.strDescription = pelmMachineChild->getValue();
else if (pelmMachineChild->nameEquals("Teleporter"))
- {
- pelmMachineChild->getAttributeValue("enabled", machineUserData.fTeleporterEnabled);
- pelmMachineChild->getAttributeValue("port", machineUserData.uTeleporterPort);
- pelmMachineChild->getAttributeValue("address", machineUserData.strTeleporterAddress);
- pelmMachineChild->getAttributeValue("password", machineUserData.strTeleporterPassword);
- }
+ readTeleporter(pelmMachineChild, &machineUserData);
else if (pelmMachineChild->nameEquals("FaultTolerance"))
{
Utf8Str strFaultToleranceSate;
@@ -3372,6 +3513,12 @@ void MachineConfigFile::readMachine(const xml::ElementNode &elmMachine)
}
else if (pelmMachineChild->nameEquals("MediaRegistry"))
readMediaRegistry(*pelmMachineChild, mediaRegistry);
+ else if (pelmMachineChild->nameEquals("Debugging"))
+ readDebugging(pelmMachineChild, &debugging);
+ else if (pelmMachineChild->nameEquals("Autostart"))
+ readAutostart(pelmMachineChild, &autostart);
+ else if (pelmMachineChild->nameEquals("Groups"))
+ readGroups(pelmMachineChild, &machineUserData.llGroups);
}
if (m->sv < SettingsVersion_v1_9)
@@ -3490,36 +3637,36 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
if ( (m->sv >= SettingsVersion_v1_10)
)
{
- xml::ElementNode *pelmHid = pelmHardware->createChild("HID");
- const char *pcszHid;
+ xml::ElementNode *pelmHID = pelmHardware->createChild("HID");
+ const char *pcszHID;
- switch (hw.pointingHidType)
+ switch (hw.pointingHIDType)
{
- case PointingHidType_USBMouse: pcszHid = "USBMouse"; break;
- case PointingHidType_USBTablet: pcszHid = "USBTablet"; break;
- case PointingHidType_PS2Mouse: pcszHid = "PS2Mouse"; break;
- case PointingHidType_ComboMouse: pcszHid = "ComboMouse"; break;
- case PointingHidType_None: pcszHid = "None"; break;
- default: Assert(false); pcszHid = "PS2Mouse"; break;
+ case PointingHIDType_USBMouse: pcszHID = "USBMouse"; break;
+ case PointingHIDType_USBTablet: pcszHID = "USBTablet"; break;
+ case PointingHIDType_PS2Mouse: pcszHID = "PS2Mouse"; break;
+ case PointingHIDType_ComboMouse: pcszHID = "ComboMouse"; break;
+ case PointingHIDType_None: pcszHID = "None"; break;
+ default: Assert(false); pcszHID = "PS2Mouse"; break;
}
- pelmHid->setAttribute("Pointing", pcszHid);
+ pelmHID->setAttribute("Pointing", pcszHID);
- switch (hw.keyboardHidType)
+ switch (hw.keyboardHIDType)
{
- case KeyboardHidType_USBKeyboard: pcszHid = "USBKeyboard"; break;
- case KeyboardHidType_PS2Keyboard: pcszHid = "PS2Keyboard"; break;
- case KeyboardHidType_ComboKeyboard: pcszHid = "ComboKeyboard"; break;
- case KeyboardHidType_None: pcszHid = "None"; break;
- default: Assert(false); pcszHid = "PS2Keyboard"; break;
+ case KeyboardHIDType_USBKeyboard: pcszHID = "USBKeyboard"; break;
+ case KeyboardHIDType_PS2Keyboard: pcszHID = "PS2Keyboard"; break;
+ case KeyboardHIDType_ComboKeyboard: pcszHID = "ComboKeyboard"; break;
+ case KeyboardHIDType_None: pcszHID = "None"; break;
+ default: Assert(false); pcszHID = "PS2Keyboard"; break;
}
- pelmHid->setAttribute("Keyboard", pcszHid);
+ pelmHID->setAttribute("Keyboard", pcszHID);
}
if ( (m->sv >= SettingsVersion_v1_10)
)
{
- xml::ElementNode *pelmHpet = pelmHardware->createChild("HPET");
- pelmHpet->setAttribute("enabled", hw.fHpetEnabled);
+ xml::ElementNode *pelmHPET = pelmHardware->createChild("HPET");
+ pelmHPET->setAttribute("enabled", hw.fHPETEnabled);
}
if ( (m->sv >= SettingsVersion_v1_11)
@@ -3568,6 +3715,15 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
if (m->sv >= SettingsVersion_v1_8)
pelmDisplay->setAttribute("accelerate2DVideo", hw.fAccelerate2DVideo);
+ xml::ElementNode *pelmVideoCapture = pelmHardware->createChild("VideoRecording");
+
+ if (m->sv >= SettingsVersion_v1_12)
+ {
+ pelmVideoCapture->setAttribute("enabled", hw.fVideoCaptureEnabled);
+ pelmVideoCapture->setAttribute("file", hw.strVideoCaptureFile);
+ pelmVideoCapture->setAttribute("horzRes", hw.ulVideoCaptureHorzRes);
+ pelmVideoCapture->setAttribute("vertRes", hw.ulVideoCaptureVertRes);
+ }
xml::ElementNode *pelmVRDE = pelmHardware->createChild("RemoteDisplay");
pelmVRDE->setAttribute("enabled", hw.vrdeSettings.fEnabled);
@@ -3951,25 +4107,36 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
const char *pcszClip;
switch (hw.clipboardMode)
{
- case ClipboardMode_Disabled: pcszClip = "Disabled"; break;
+ default: /*case ClipboardMode_Disabled:*/ pcszClip = "Disabled"; break;
case ClipboardMode_HostToGuest: pcszClip = "HostToGuest"; break;
case ClipboardMode_GuestToHost: pcszClip = "GuestToHost"; break;
- default: /*case ClipboardMode_Bidirectional:*/ pcszClip = "Bidirectional"; break;
+ case ClipboardMode_Bidirectional: pcszClip = "Bidirectional"; break;
}
pelmClip->setAttribute("mode", pcszClip);
+ xml::ElementNode *pelmDragAndDrop = pelmHardware->createChild("DragAndDrop");
+ const char *pcszDragAndDrop;
+ switch (hw.dragAndDropMode)
+ {
+ default: /*case DragAndDropMode_Disabled:*/ pcszDragAndDrop = "Disabled"; break;
+ case DragAndDropMode_HostToGuest: pcszDragAndDrop = "HostToGuest"; break;
+ case DragAndDropMode_GuestToHost: pcszDragAndDrop = "GuestToHost"; break;
+ case DragAndDropMode_Bidirectional: pcszDragAndDrop = "Bidirectional"; break;
+ }
+ pelmDragAndDrop->setAttribute("mode", pcszDragAndDrop);
+
if (m->sv >= SettingsVersion_v1_10)
{
- xml::ElementNode *pelmIo = pelmHardware->createChild("IO");
- xml::ElementNode *pelmIoCache;
+ xml::ElementNode *pelmIO = pelmHardware->createChild("IO");
+ xml::ElementNode *pelmIOCache;
- pelmIoCache = pelmIo->createChild("IoCache");
- pelmIoCache->setAttribute("enabled", hw.ioSettings.fIoCacheEnabled);
- pelmIoCache->setAttribute("size", hw.ioSettings.ulIoCacheSize);
+ pelmIOCache = pelmIO->createChild("IoCache");
+ pelmIOCache->setAttribute("enabled", hw.ioSettings.fIOCacheEnabled);
+ pelmIOCache->setAttribute("size", hw.ioSettings.ulIOCacheSize);
if (m->sv >= SettingsVersion_v1_11)
{
- xml::ElementNode *pelmBandwidthGroups = pelmIo->createChild("BandwidthGroups");
+ xml::ElementNode *pelmBandwidthGroups = pelmIO->createChild("BandwidthGroups");
for (BandwidthGroupList::const_iterator it = hw.ioSettings.llBandwidthGroups.begin();
it != hw.ioSettings.llBandwidthGroups.end();
++it)
@@ -3984,23 +4151,26 @@ void MachineConfigFile::buildHardwareXML(xml::ElementNode &elmParent,
default: /* BandwidthGrouptype_Disk */ pcszType = "Disk"; break;
}
pelmThis->setAttribute("type", pcszType);
- pelmThis->setAttribute("maxMbPerSec", gr.cMaxMbPerSec);
+ if (m->sv >= SettingsVersion_v1_13)
+ pelmThis->setAttribute("maxBytesPerSec", gr.cMaxBytesPerSec);
+ else
+ pelmThis->setAttribute("maxMbPerSec", gr.cMaxBytesPerSec / _1M);
}
}
}
if (m->sv >= SettingsVersion_v1_12)
{
- xml::ElementNode *pelmPci = pelmHardware->createChild("HostPci");
- xml::ElementNode *pelmPciDevices = pelmPci->createChild("Devices");
+ xml::ElementNode *pelmPCI = pelmHardware->createChild("HostPci");
+ xml::ElementNode *pelmPCIDevices = pelmPCI->createChild("Devices");
- for (HostPciDeviceAttachmentList::const_iterator it = hw.pciAttachments.begin();
+ for (HostPCIDeviceAttachmentList::const_iterator it = hw.pciAttachments.begin();
it != hw.pciAttachments.end();
++it)
{
- const HostPciDeviceAttachment &hpda = *it;
+ const HostPCIDeviceAttachment &hpda = *it;
- xml::ElementNode *pelmThis = pelmPciDevices->createChild("Device");
+ xml::ElementNode *pelmThis = pelmPCIDevices->createChild("Device");
pelmThis->setAttribute("host", hpda.uHostAddress);
pelmThis->setAttribute("guest", hpda.uGuestAddress);
@@ -4070,9 +4240,9 @@ void MachineConfigFile::buildNetworkXML(NetworkAttachmentType_T mode,
pelmNAT->setAttribute("tcpsnd", nic.nat.u32TcpSnd);
xml::ElementNode *pelmDNS;
pelmDNS = pelmNAT->createChild("DNS");
- pelmDNS->setAttribute("pass-domain", nic.nat.fDnsPassDomain);
- pelmDNS->setAttribute("use-proxy", nic.nat.fDnsProxy);
- pelmDNS->setAttribute("use-host-resolver", nic.nat.fDnsUseHostResolver);
+ pelmDNS->setAttribute("pass-domain", nic.nat.fDNSPassDomain);
+ pelmDNS->setAttribute("use-proxy", nic.nat.fDNSProxy);
+ pelmDNS->setAttribute("use-host-resolver", nic.nat.fDNSUseHostResolver);
xml::ElementNode *pelmAlias;
pelmAlias = pelmNAT->createChild("Alias");
@@ -4080,18 +4250,18 @@ void MachineConfigFile::buildNetworkXML(NetworkAttachmentType_T mode,
pelmAlias->setAttribute("proxy-only", nic.nat.fAliasProxyOnly);
pelmAlias->setAttribute("use-same-ports", nic.nat.fAliasUseSamePorts);
- if ( nic.nat.strTftpPrefix.length()
- || nic.nat.strTftpBootFile.length()
- || nic.nat.strTftpNextServer.length())
+ if ( nic.nat.strTFTPPrefix.length()
+ || nic.nat.strTFTPBootFile.length()
+ || nic.nat.strTFTPNextServer.length())
{
xml::ElementNode *pelmTFTP;
pelmTFTP = pelmNAT->createChild("TFTP");
- if (nic.nat.strTftpPrefix.length())
- pelmTFTP->setAttribute("prefix", nic.nat.strTftpPrefix);
- if (nic.nat.strTftpBootFile.length())
- pelmTFTP->setAttribute("boot-file", nic.nat.strTftpBootFile);
- if (nic.nat.strTftpNextServer.length())
- pelmTFTP->setAttribute("next-server", nic.nat.strTftpNextServer);
+ if (nic.nat.strTFTPPrefix.length())
+ pelmTFTP->setAttribute("prefix", nic.nat.strTFTPPrefix);
+ if (nic.nat.strTFTPBootFile.length())
+ pelmTFTP->setAttribute("boot-file", nic.nat.strTFTPBootFile);
+ if (nic.nat.strTFTPNextServer.length())
+ pelmTFTP->setAttribute("next-server", nic.nat.strTFTPNextServer);
}
for (NATRuleList::const_iterator rule = nic.nat.llRules.begin();
rule != nic.nat.llRules.end(); ++rule)
@@ -4255,6 +4425,8 @@ void MachineConfigFile::buildStorageControllersXML(xml::ElementNode &elmParent,
pcszType = "HardDisk";
if (att.fNonRotational)
pelmDevice->setAttribute("nonrotational", att.fNonRotational);
+ if (att.fDiscard)
+ pelmDevice->setAttribute("discard", att.fDiscard);
break;
case DeviceType_DVD:
@@ -4300,6 +4472,78 @@ void MachineConfigFile::buildStorageControllersXML(xml::ElementNode &elmParent,
}
/**
+ * Creates a <Debugging> node under elmParent and then writes out the XML
+ * keys under that. Called for both the <Machine> node and for snapshots.
+ *
+ * @param pElmParent Pointer to the parent element.
+ * @param pDbg Pointer to the debugging settings.
+ */
+void MachineConfigFile::buildDebuggingXML(xml::ElementNode *pElmParent, const Debugging *pDbg)
+{
+ if (m->sv < SettingsVersion_v1_13 || pDbg->areDefaultSettings())
+ return;
+
+ xml::ElementNode *pElmDebugging = pElmParent->createChild("Debugging");
+ xml::ElementNode *pElmTracing = pElmDebugging->createChild("Tracing");
+ pElmTracing->setAttribute("enabled", pDbg->fTracingEnabled);
+ pElmTracing->setAttribute("allowTracingToAccessVM", pDbg->fAllowTracingToAccessVM);
+ pElmTracing->setAttribute("config", pDbg->strTracingConfig);
+}
+
+/**
+ * Creates a <Autostart> node under elmParent and then writes out the XML
+ * keys under that. Called for both the <Machine> node and for snapshots.
+ *
+ * @param pElmParent Pointer to the parent element.
+ * @param pAutostart Pointer to the autostart settings.
+ */
+void MachineConfigFile::buildAutostartXML(xml::ElementNode *pElmParent, const Autostart *pAutostart)
+{
+ const char *pcszAutostop = NULL;
+
+ if (m->sv < SettingsVersion_v1_13 || pAutostart->areDefaultSettings())
+ return;
+
+ xml::ElementNode *pElmAutostart = pElmParent->createChild("Autostart");
+ pElmAutostart->setAttribute("enabled", pAutostart->fAutostartEnabled);
+ pElmAutostart->setAttribute("delay", pAutostart->uAutostartDelay);
+
+ switch (pAutostart->enmAutostopType)
+ {
+ case AutostopType_Disabled: pcszAutostop = "Disabled"; break;
+ case AutostopType_SaveState: pcszAutostop = "SaveState"; break;
+ case AutostopType_PowerOff: pcszAutostop = "PowerOff"; break;
+ case AutostopType_AcpiShutdown: pcszAutostop = "AcpiShutdown"; break;
+ default: Assert(false); pcszAutostop = "Disabled"; break;
+ }
+ pElmAutostart->setAttribute("autostop", pcszAutostop);
+}
+
+/**
+ * Creates a <Groups> node under elmParent and then writes out the XML
+ * keys under that. Called for the <Machine> node only.
+ *
+ * @param pElmParent Pointer to the parent element.
+ * @param pllGroups Pointer to the groups list.
+ */
+void MachineConfigFile::buildGroupsXML(xml::ElementNode *pElmParent, const StringsList *pllGroups)
+{
+ if ( m->sv < SettingsVersion_v1_13 || pllGroups->size() == 0
+ || (pllGroups->size() == 1 && pllGroups->front() == "/"))
+ return;
+
+ xml::ElementNode *pElmGroups = pElmParent->createChild("Groups");
+ for (StringsList::const_iterator it = pllGroups->begin();
+ it != pllGroups->end();
+ ++it)
+ {
+ const Utf8Str &group = *it;
+ xml::ElementNode *pElmGroup = pElmGroups->createChild("Group");
+ pElmGroup->setAttribute("name", group);
+ }
+}
+
+/**
* Writes a single snapshot into the DOM tree. Initially this gets called from MachineConfigFile::write()
* for the root snapshot of a machine, if present; elmParent then points to the <Snapshots> node under the
* <Machine> node to which <Snapshot> must be added. This may then recurse for child snapshots.
@@ -4328,6 +4572,9 @@ void MachineConfigFile::buildSnapshotXML(xml::ElementNode &elmParent,
NULL); /* pllElementsWithUuidAttributes */
// we only skip removable media for OVF, but we never get here for OVF
// since snapshots never get written then
+ buildDebuggingXML(pelmSnapshot, &snap.debugging);
+ buildAutostartXML(pelmSnapshot, &snap.autostart);
+ // note: Groups exist only for Machine, not for Snapshot
if (snap.llChildSnapshots.size())
{
@@ -4396,6 +4643,8 @@ void MachineConfigFile::buildMachineXML(xml::ElementNode &elmMachine,
elmMachine.setAttribute("uuid", uuid.toStringCurly());
elmMachine.setAttribute("name", machineUserData.strName);
+ if (machineUserData.fDirectoryIncludesUUID)
+ elmMachine.setAttribute("directoryIncludesUUID", machineUserData.fDirectoryIncludesUUID);
if (!machineUserData.fNameSync)
elmMachine.setAttribute("nameSync", machineUserData.fNameSync);
if (machineUserData.strDescription.length())
@@ -4475,6 +4724,9 @@ void MachineConfigFile::buildMachineXML(xml::ElementNode &elmMachine,
storageMachine,
!!(fl & BuildMachineXML_SkipRemovableMedia),
pllElementsWithUuidAttributes);
+ buildDebuggingXML(&elmMachine, &debugging);
+ buildAutostartXML(&elmMachine, &autostart);
+ buildGroupsXML(&elmMachine, &machineUserData.llGroups);
}
/**
@@ -4590,6 +4842,34 @@ AudioDriverType_T MachineConfigFile::getHostDefaultAudioDriver()
*/
void MachineConfigFile::bumpSettingsVersionIfNeeded()
{
+ if (m->sv < SettingsVersion_v1_13)
+ {
+ // VirtualBox 4.2 adds tracing, autostart, UUID in directory and groups.
+ if ( !debugging.areDefaultSettings()
+ || !autostart.areDefaultSettings()
+ || machineUserData.fDirectoryIncludesUUID
+ || machineUserData.llGroups.size() > 1
+ || machineUserData.llGroups.front() != "/")
+ m->sv = SettingsVersion_v1_13;
+ }
+
+ if (m->sv < SettingsVersion_v1_13)
+ {
+ // VirtualBox 4.2 changes the units for bandwidth group limits.
+ for (BandwidthGroupList::const_iterator it = hardwareMachine.ioSettings.llBandwidthGroups.begin();
+ it != hardwareMachine.ioSettings.llBandwidthGroups.end();
+ ++it)
+ {
+ const BandwidthGroup &gr = *it;
+ if (gr.cMaxBytesPerSec % _1M)
+ {
+ // Bump version if a limit cannot be expressed in megabytes
+ m->sv = SettingsVersion_v1_13;
+ break;
+ }
+ }
+ }
+
if (m->sv < SettingsVersion_v1_12)
{
// 4.1: Emulated USB devices.
@@ -4628,7 +4908,7 @@ void MachineConfigFile::bumpSettingsVersionIfNeeded()
if (m->sv < SettingsVersion_v1_11)
{
// VirtualBox 4.0 adds HD audio, CPU priorities, fault tolerance,
- // per-machine media registries, VRDE, JRockitVE, bandwidth gorups,
+ // per-machine media registries, VRDE, JRockitVE, bandwidth groups,
// ICH9 chipset
if ( hardwareMachine.audioAdapter.controllerType == AudioControllerType_HDA
|| hardwareMachine.ulCpuExecutionCap != 100
@@ -4819,16 +5099,16 @@ void MachineConfigFile::bumpSettingsVersionIfNeeded()
// VirtualBox 3.2: Check for non default I/O settings
if (m->sv < SettingsVersion_v1_10)
{
- if ( (hardwareMachine.ioSettings.fIoCacheEnabled != true)
- || (hardwareMachine.ioSettings.ulIoCacheSize != 5)
+ if ( (hardwareMachine.ioSettings.fIOCacheEnabled != true)
+ || (hardwareMachine.ioSettings.ulIOCacheSize != 5)
// and page fusion
|| (hardwareMachine.fPageFusionEnabled)
// and CPU hotplug, RTC timezone control, HID type and HPET
|| machineUserData.fRTCUseUTC
|| hardwareMachine.fCpuHotPlug
- || hardwareMachine.pointingHidType != PointingHidType_PS2Mouse
- || hardwareMachine.keyboardHidType != KeyboardHidType_PS2Keyboard
- || hardwareMachine.fHpetEnabled
+ || hardwareMachine.pointingHIDType != PointingHIDType_PS2Mouse
+ || hardwareMachine.keyboardHIDType != KeyboardHIDType_PS2Keyboard
+ || hardwareMachine.fHPETEnabled
)
m->sv = SettingsVersion_v1_10;
}
@@ -4858,15 +5138,15 @@ void MachineConfigFile::bumpSettingsVersionIfNeeded()
|| netit->nat.u32SockSnd != 0
|| netit->nat.u32TcpRcv != 0
|| netit->nat.u32TcpSnd != 0
- || !netit->nat.fDnsPassDomain
- || netit->nat.fDnsProxy
- || netit->nat.fDnsUseHostResolver
+ || !netit->nat.fDNSPassDomain
+ || netit->nat.fDNSProxy
+ || netit->nat.fDNSUseHostResolver
|| netit->nat.fAliasLog
|| netit->nat.fAliasProxyOnly
|| netit->nat.fAliasUseSamePorts
- || netit->nat.strTftpPrefix.length()
- || netit->nat.strTftpBootFile.length()
- || netit->nat.strTftpNextServer.length()
+ || netit->nat.strTFTPPrefix.length()
+ || netit->nat.strTFTPBootFile.length()
+ || netit->nat.strTFTPNextServer.length()
|| netit->nat.llRules.size()
)
)
diff --git a/src/VBox/Main/xml/SettingsConverter.xsl b/src/VBox/Main/xml/SettingsConverter.xsl
index fc56ce3a9..9a31a4ccc 100644
--- a/src/VBox/Main/xml/SettingsConverter.xsl
+++ b/src/VBox/Main/xml/SettingsConverter.xsl
@@ -6,15 +6,15 @@
*
* Template to convert old VirtualBox settings files to the most recent format.
- Copyright (C) 2006-2009 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2006-2009 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsl:stylesheet version="1.0"
diff --git a/src/VBox/Main/xml/VirtualBox-settings-common.xsd b/src/VBox/Main/xml/VirtualBox-settings-common.xsd
index 7345d5fec..c960afa7e 100644
--- a/src/VBox/Main/xml/VirtualBox-settings-common.xsd
+++ b/src/VBox/Main/xml/VirtualBox-settings-common.xsd
@@ -6,15 +6,15 @@
* Oracle VM VirtualBox Settings Schema
* Common definitions
- Copyright (C) 2004-2011 Oracle Corporation
-
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ Copyright (C) 2004-2012 Oracle Corporation
+
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsd:schema
@@ -28,7 +28,7 @@
<xsd:annotation>
<xsd:documentation xml:lang="en">
Oracle VM VirtualBox Settings Schema (common definitions).
- Copyright (c) 2004-2010 Oracle Corporation
+ Copyright (c) 2004-2012 Oracle Corporation
</xsd:documentation>
</xsd:annotation>
@@ -134,81 +134,6 @@
</xsd:restriction>
</xsd:simpleType>
-<xsd:simpleType name="TGuestOSType">
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="Other"/>
- <xsd:enumeration value="DOS"/>
- <xsd:enumeration value="Netware"/>
- <xsd:enumeration value="L4"/>
- <xsd:enumeration value="Windows31"/>
- <xsd:enumeration value="Windows95"/>
- <xsd:enumeration value="Windows98"/>
- <xsd:enumeration value="WindowsMe"/>
- <xsd:enumeration value="WindowsNT4"/>
- <xsd:enumeration value="Windows2000"/>
- <xsd:enumeration value="WindowsXP"/>
- <xsd:enumeration value="WindowsXP_64"/>
- <xsd:enumeration value="Windows2003"/>
- <xsd:enumeration value="Windows2003_64"/>
- <xsd:enumeration value="WindowsVista"/>
- <xsd:enumeration value="WindowsVista_64"/>
- <xsd:enumeration value="Windows2008"/>
- <xsd:enumeration value="Windows2008_64"/>
- <xsd:enumeration value="Windows7"/>
- <xsd:enumeration value="Windows7_64"/>
- <xsd:enumeration value="Windows8"/>
- <xsd:enumeration value="Windows8_64"/>
- <xsd:enumeration value="WindowsNT"/>
- <xsd:enumeration value="OS2Warp3"/>
- <xsd:enumeration value="OS2Warp4"/>
- <xsd:enumeration value="OS2Warp45"/>
- <xsd:enumeration value="OS2eCS"/>
- <xsd:enumeration value="OS2"/>
- <xsd:enumeration value="Linux22"/>
- <xsd:enumeration value="Linux24"/>
- <xsd:enumeration value="Linux24_64"/>
- <xsd:enumeration value="Linux26"/>
- <xsd:enumeration value="Linux26_64"/>
- <xsd:enumeration value="ArchLinux"/>
- <xsd:enumeration value="ArchLinux_64"/>
- <xsd:enumeration value="Debian"/>
- <xsd:enumeration value="Debian_64"/>
- <xsd:enumeration value="OpenSUSE"/>
- <xsd:enumeration value="OpenSUSE_64"/>
- <xsd:enumeration value="Fedora"/>
- <xsd:enumeration value="Fedora_64"/>
- <xsd:enumeration value="Gentoo"/>
- <xsd:enumeration value="Gentoo_64"/>
- <xsd:enumeration value="Mandriva"/>
- <xsd:enumeration value="Mandriva_64"/>
- <xsd:enumeration value="RedHat"/>
- <xsd:enumeration value="RedHat_64"/>
- <xsd:enumeration value="Turbolinux"/>
- <xsd:enumeration value="Turbolinux_64"/>
- <xsd:enumeration value="Ubuntu"/>
- <xsd:enumeration value="Ubuntu_64"/>
- <xsd:enumeration value="Xandros"/>
- <xsd:enumeration value="Xandros_64"/>
- <xsd:enumeration value="Oracle"/>
- <xsd:enumeration value="Oracle_64"/>
- <xsd:enumeration value="Linux"/>
- <xsd:enumeration value="FreeBSD"/>
- <xsd:enumeration value="FreeBSD_64"/>
- <xsd:enumeration value="OpenBSD"/>
- <xsd:enumeration value="OpenBSD_64"/>
- <xsd:enumeration value="NetBSD"/>
- <xsd:enumeration value="NetBSD_64"/>
- <xsd:enumeration value="Solaris"/>
- <xsd:enumeration value="Solaris_64"/>
- <xsd:enumeration value="OpenSolaris"/>
- <xsd:enumeration value="OpenSolaris_64"/>
- <xsd:enumeration value="QNX"/>
- <xsd:enumeration value="MacOS"/>
- <xsd:enumeration value="MacOS_64"/>
- <xsd:enumeration value="JRockitVE"/>
- </xsd:restriction>
-</xsd:simpleType>
-
<xsd:simpleType name="TAuthType">
<xsd:restriction base="xsd:string">
@@ -254,6 +179,15 @@
</xsd:restriction>
</xsd:simpleType>
+<xsd:simpleType name="TDragAndDropMode">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="Disabled"/>
+ <xsd:enumeration value="HostToGuest"/>
+ <xsd:enumeration value="GuestToHost"/>
+ <xsd:enumeration value="Bidirectional"/>
+ </xsd:restriction>
+</xsd:simpleType>
+
<xsd:simpleType name="TPortMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Disconnected"/>
@@ -525,6 +459,21 @@
</xsd:complexType>
<xsd:complexType name="TDisplay">
+ <xsd:element name="VideoRecording">
+ <xsd:complexType>
+ <xsd:attribute name="enabled" type="xsd:boolean"/>
+ <xsd:attribute name="file" type="xsd:string"/>
+ <xsd:attribute name="horzRes" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:unsignedInt">
+ <xsd:minInclusive value="4"/>
+ <xsd:maxInclusive value="2097152"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="vertRes" type="xsd:unsignedInt"/>
+ </xsd:complexType>
+ </xsd:element>
<xsd:attribute name="VRAMSize" use="required">
<xsd:simpleType>
<xsd:restriction base="xsd:unsignedInt">
@@ -533,10 +482,11 @@
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
+ <!-- This should be in sync with VBOX_VIDEO_MAX_SCREENS in VBoxVideoVBE.h -->
<xsd:attribute name="monitorCount" default="1">
<xsd:simpleType>
<xsd:restriction base="xsd:unsignedInt">
- <xsd:maxInclusive value="8"/>
+ <xsd:maxInclusive value="64"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
@@ -782,14 +732,7 @@
<!-- The DisabledModes tag is not part of this XSD file right now. -->
</xsd:choice>
<xsd:attribute name="type" type="TNetworkAdapterType" default="Am79C970A"/>
- <xsd:attribute name="slot" use="required">
- <xsd:simpleType>
- <xsd:restriction base="xsd:unsignedInt">
- <xsd:minInclusive value="0"/>
- <xsd:maxExclusive value="8"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
+ <xsd:attribute name="slot" type="xsd:unsignedInt" use="required"/>
<xsd:attribute name="enabled" type="xsd:boolean" use="required"/>
<xsd:attribute name="MACAddress">
<xsd:simpleType>
@@ -802,6 +745,7 @@
<xsd:attribute name="speed" type="xsd:unsignedInt" default="1000000"/>
<xsd:attribute name="trace" type="xsd:boolean" default="false"/>
<xsd:attribute name="tracefile" type="xsd:string"/>
+ <xsd:attribute name="bandwidthGroup" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="TNetwork">
@@ -873,6 +817,10 @@
<xsd:attribute name="mode" type="TClipboardMode" use="required"/>
</xsd:complexType>
+<xsd:complexType name="TDragAndDrop">
+ <xsd:attribute name="mode" type="TDragAndDropMode" use="required"/>
+</xsd:complexType>
+
<xsd:complexType name="TGuest">
<xsd:attribute name="memoryBalloonSize" type="xsd:unsignedInt" default="0"/>
<xsd:attribute name="statisticsUpdateInterval" type="xsd:unsignedInt" default="0"/>
@@ -945,6 +893,7 @@
</xsd:unique>
</xsd:element>
<xsd:element name="Clipboard" type="TClipboard"/>
+ <xsd:element name="DragAndDrop" type="TDragAndDrop"/>
<xsd:element name="Guest" type="TGuest"/>
<xsd:element name="GuestProperties" type="TGuestProperties" minOccurs="0">
<xsd:unique name="THardware-GuestProperties-GuestProperty">
@@ -966,7 +915,7 @@
</xsd:all>
<xsd:attribute name="name" type="TNonEmptyString" use="required"/>
<xsd:attribute name="nameSync" type="xsd:boolean" default="true"/>
- <xsd:attribute name="OSType" type="TGuestOSType" use="required"/>
+ <xsd:attribute name="OSType" type="TNonEmptyString" use="required"/>
<xsd:attribute name="uuid" type="TNonNullUUID" use="required"/>
<xsd:attribute name="stateFile" type="TLocalFile"/>
<xsd:attribute name="currentSnapshot" type="TNonNullUUID"/>
diff --git a/src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd b/src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd
index d08048e9b..d874c9c97 100644
--- a/src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd
+++ b/src/VBox/Main/xml/VirtualBox-settings-freebsd.xsd
@@ -5,15 +5,15 @@
*
* Oracle VM VirtualBox Settings Schema Version 1.0-freebsd
- Copyright (C) 2004-2010 Oracle Corporation
+ Copyright (C) 2004-2010 Oracle Corporation
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsd:schema
diff --git a/src/VBox/Main/xml/VirtualBox-settings-linux.xsd b/src/VBox/Main/xml/VirtualBox-settings-linux.xsd
index 20fad8095..461521eb6 100644
--- a/src/VBox/Main/xml/VirtualBox-settings-linux.xsd
+++ b/src/VBox/Main/xml/VirtualBox-settings-linux.xsd
@@ -5,15 +5,15 @@
*
* Oracle VM VirtualBox Settings Schema Version 1.0-linux
- Copyright (C) 2004-2010 Oracle Corporation
+ Copyright (C) 2004-2010 Oracle Corporation
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsd:schema
diff --git a/src/VBox/Main/xml/VirtualBox-settings-macosx.xsd b/src/VBox/Main/xml/VirtualBox-settings-macosx.xsd
index 5d2d08d6d..1d2efa760 100644
--- a/src/VBox/Main/xml/VirtualBox-settings-macosx.xsd
+++ b/src/VBox/Main/xml/VirtualBox-settings-macosx.xsd
@@ -5,15 +5,15 @@
*
* Oracle VM VirtualBox Settings Schema Version 1.0-macosx
- Copyright (C) 2004-2010 Oracle Corporation
+ Copyright (C) 2004-2010 Oracle Corporation
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsd:schema
diff --git a/src/VBox/Main/xml/VirtualBox-settings-os2.xsd b/src/VBox/Main/xml/VirtualBox-settings-os2.xsd
index 6f53836c4..771a97385 100644
--- a/src/VBox/Main/xml/VirtualBox-settings-os2.xsd
+++ b/src/VBox/Main/xml/VirtualBox-settings-os2.xsd
@@ -6,15 +6,15 @@
*
* Oracle VM VirtualBox Settings Schema Version 1.0-os2
*
- Copyright (C) 2004-2010 Oracle Corporation
+ Copyright (C) 2004-2010 Oracle Corporation
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsd:schema
diff --git a/src/VBox/Main/xml/VirtualBox-settings-solaris.xsd b/src/VBox/Main/xml/VirtualBox-settings-solaris.xsd
index 6af3eac98..6e504e5a2 100644
--- a/src/VBox/Main/xml/VirtualBox-settings-solaris.xsd
+++ b/src/VBox/Main/xml/VirtualBox-settings-solaris.xsd
@@ -5,15 +5,15 @@
*
* Oracle VM VirtualBox Settings Schema Version 1.0-solaris
- Copyright (C) 2004-2010 Oracle Corporation
+ Copyright (C) 2004-2010 Oracle Corporation
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsd:schema
diff --git a/src/VBox/Main/xml/VirtualBox-settings-windows.xsd b/src/VBox/Main/xml/VirtualBox-settings-windows.xsd
index 09efa71b5..8bdae19ef 100644
--- a/src/VBox/Main/xml/VirtualBox-settings-windows.xsd
+++ b/src/VBox/Main/xml/VirtualBox-settings-windows.xsd
@@ -5,15 +5,15 @@
*
* Oracle VM VirtualBox Settings Schema Version 1.0-windows
- Copyright (C) 2004-2010 Oracle Corporation
+ Copyright (C) 2004-2010 Oracle Corporation
- This file is part of VirtualBox Open Source Edition (OSE), as
- available from http://www.virtualbox.org. This file is free software;
- you can redistribute it and/or modify it under the terms of the GNU
- General Public License (GPL) as published by the Free Software
- Foundation, in version 2 as it comes in the "COPYING" file of the
- VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ This file is part of VirtualBox Open Source Edition (OSE), as
+ available from http://www.virtualbox.org. This file is free software;
+ you can redistribute it and/or modify it under the terms of the GNU
+ General Public License (GPL) as published by the Free Software
+ Foundation, in version 2 as it comes in the "COPYING" file of the
+ VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-->
<xsd:schema
diff --git a/src/VBox/Main/xml/ovfreader.cpp b/src/VBox/Main/xml/ovfreader.cpp
index eb685fd31..3d2455700 100644
--- a/src/VBox/Main/xml/ovfreader.cpp
+++ b/src/VBox/Main/xml/ovfreader.cpp
@@ -466,7 +466,8 @@ void OVFReader::HandleVirtualSystemContent(const xml::ElementNode *pelmVirtualSy
i.strPoolID = pelmItemChild->getValue();
else if (!strcmp(pcszItemChildName, "BusNumber")) // seen in some old OVF, but it's not listed in the OVF specs
pelmItemChild->copyValue(i.ulBusNumber);
- else
+ else if ( pelmItemChild->getPrefix() == NULL
+ || strcmp(pelmItemChild->getPrefix(), "vmw"))
throw OVFLogicError(N_("Error reading \"%s\": unknown element \"%s\" under Item element, line %d"),
m_strPath.c_str(),
pcszItemChildName,