SystemPropertiesImpl.cpp revision 35779b5ff92d92bc215bf98458583ed33162762f
/* $Id$ */
/** @file
* VirtualBox COM class implementation
*/
/*
* Copyright (C) 2006-2013 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 "SystemPropertiesImpl.h"
#include "VirtualBoxImpl.h"
#include "MachineImpl.h"
#ifdef VBOX_WITH_EXTPACK
# include "ExtPackManagerImpl.h"
#endif
#include "AutoCaller.h"
#include "Global.h"
#include "Logging.h"
#include "AutostartDb.h"
// generated header
#include "SchemaDefs.h"
#include <iprt/dir.h>
#include <iprt/ldr.h>
#include <iprt/path.h>
#include <iprt/string.h>
#include <iprt/cpp/utils.h>
#include <VBox/err.h>
#include <VBox/param.h>
#include <VBox/settings.h>
#include <VBox/vd.h>
// defines
/////////////////////////////////////////////////////////////////////////////
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
SystemProperties::SystemProperties()
: mParent(NULL),
m(new settings::SystemProperties)
{
}
SystemProperties::~SystemProperties()
{
delete m;
}
HRESULT SystemProperties::FinalConstruct()
{
return BaseFinalConstruct();
}
void SystemProperties::FinalRelease()
{
uninit();
BaseFinalRelease();
}
// public methods only for internal purposes
/////////////////////////////////////////////////////////////////////////////
/**
* Initializes the system information object.
*
* @returns COM result indicator
*/
HRESULT SystemProperties::init(VirtualBox *aParent)
{
LogFlowThisFunc(("aParent=%p\n", aParent));
ComAssertRet(aParent, E_FAIL);
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
AssertReturn(autoInitSpan.isOk(), E_FAIL);
unconst(mParent) = aParent;
setDefaultMachineFolder(Utf8Str::Empty);
setLoggingLevel(Utf8Str::Empty);
setDefaultHardDiskFormat(Utf8Str::Empty);
setVRDEAuthLibrary(Utf8Str::Empty);
setDefaultVRDEExtPack(Utf8Str::Empty);
m->ulLogHistoryCount = 3;
/* On Windows and OS X, HW virtualization use isn't exclusive by
* default so that VT-x or AMD-V can be shared with other
* hypervisors without requiring user intervention.
* NB: See also SystemProperties constructor in settings.h
*/
#if defined(RT_OS_DARWIN) || defined(RT_OS_WINDOWS)
m->fExclusiveHwVirt = false;
#else
m->fExclusiveHwVirt = true;
#endif
HRESULT rc = S_OK;
/* Fetch info of all available hd backends. */
/// @todo NEWMEDIA VDBackendInfo needs to be improved to let us enumerate
/// any number of backends
VDBACKENDINFO aVDInfo[100];
unsigned cEntries;
int vrc = VDBackendInfo(RT_ELEMENTS(aVDInfo), aVDInfo, &cEntries);
AssertRC(vrc);
if (RT_SUCCESS(vrc))
{
for (unsigned i = 0; i < cEntries; ++ i)
{
ComObjPtr<MediumFormat> hdf;
rc = hdf.createObject();
if (FAILED(rc)) break;
rc = hdf->init(&aVDInfo[i]);
if (FAILED(rc)) break;
m_llMediumFormats.push_back(hdf);
}
}
/* Confirm a successful initialization */
if (SUCCEEDED(rc))
autoInitSpan.setSucceeded();
return rc;
}
/**
* Uninitializes the instance and sets the ready flag to FALSE.
* Called either from FinalRelease() or by the parent when it gets destroyed.
*/
void SystemProperties::uninit()
{
LogFlowThisFunc(("\n"));
/* Enclose the state transition Ready->InUninit->NotReady */
AutoUninitSpan autoUninitSpan(this);
if (autoUninitSpan.uninitDone())
return;
unconst(mParent) = NULL;
}
// ISystemProperties properties
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP SystemProperties::COMGETTER(MinGuestRAM)(ULONG *minRAM)
{
CheckComArgOutPointerValid(minRAM);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
AssertCompile(MM_RAM_MIN_IN_MB >= SchemaDefs::MinGuestRAM);
*minRAM = MM_RAM_MIN_IN_MB;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(MaxGuestRAM)(ULONG *maxRAM)
{
CheckComArgOutPointerValid(maxRAM);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
AssertCompile(MM_RAM_MAX_IN_MB <= SchemaDefs::MaxGuestRAM);
ULONG maxRAMSys = MM_RAM_MAX_IN_MB;
ULONG maxRAMArch = maxRAMSys;
*maxRAM = RT_MIN(maxRAMSys, maxRAMArch);
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(MinGuestVRAM)(ULONG *minVRAM)
{
CheckComArgOutPointerValid(minVRAM);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
*minVRAM = SchemaDefs::MinGuestVRAM;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(MaxGuestVRAM)(ULONG *maxVRAM)
{
CheckComArgOutPointerValid(maxVRAM);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
*maxVRAM = SchemaDefs::MaxGuestVRAM;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(MinGuestCPUCount)(ULONG *minCPUCount)
{
CheckComArgOutPointerValid(minCPUCount);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
*minCPUCount = SchemaDefs::MinCPUCount; // VMM_MIN_CPU_COUNT
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(MaxGuestCPUCount)(ULONG *maxCPUCount)
{
CheckComArgOutPointerValid(maxCPUCount);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
*maxCPUCount = SchemaDefs::MaxCPUCount; // VMM_MAX_CPU_COUNT
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(MaxGuestMonitors)(ULONG *maxMonitors)
{
CheckComArgOutPointerValid(maxMonitors);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
*maxMonitors = SchemaDefs::MaxGuestMonitors;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(InfoVDSize)(LONG64 *infoVDSize)
{
CheckComArgOutPointerValid(infoVDSize);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/*
* The BIOS supports currently 32 bit LBA numbers (implementing the full
* 48 bit range is in theory trivial, but the crappy compiler makes things
* more difficult). This translates to almost 2 TiBytes (to be on the safe
* side, the reported limit is 1 MiByte less than that, as the total number
* of sectors should fit in 32 bits, too), which should be enough for the
* moment. Since the MBR partition tables support only 32bit sector numbers
* and thus the BIOS can only boot from disks smaller than 2T this is a
* rather hard limit.
*
* The virtual ATA/SATA disks support complete LBA48, and SCSI supports
* LBA64 (almost, more like LBA55 in practice), so the theoretical maximum
* disk size is 128 PiByte/16 EiByte. The GUI works nicely with 6 orders
* of magnitude, but not with 11..13 orders of magnitude.
*/
/* no need to lock, this is const */
*infoVDSize = 2 * _1T - _1M;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(SerialPortCount)(ULONG *count)
{
CheckComArgOutPointerValid(count);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
*count = SchemaDefs::SerialPortCount;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(ParallelPortCount)(ULONG *count)
{
CheckComArgOutPointerValid(count);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
*count = SchemaDefs::ParallelPortCount;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(MaxBootPosition)(ULONG *aMaxBootPosition)
{
CheckComArgOutPointerValid(aMaxBootPosition);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
*aMaxBootPosition = SchemaDefs::MaxBootPosition;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(ExclusiveHwVirt)(BOOL *aExclusiveHwVirt)
{
CheckComArgOutPointerValid(aExclusiveHwVirt);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
*aExclusiveHwVirt = m->fExclusiveHwVirt;
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(ExclusiveHwVirt)(BOOL aExclusiveHwVirt)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
m->fExclusiveHwVirt = !!aExclusiveHwVirt;
alock.release();
// VirtualBox::saveSettings() needs vbox write lock
AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
HRESULT rc = mParent->saveSettings();
return rc;
}
STDMETHODIMP SystemProperties::GetMaxNetworkAdapters(ChipsetType_T aChipset, ULONG *count)
{
CheckComArgOutPointerValid(count);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need for locking, no state */
uint32_t uResult = Global::getMaxNetworkAdapters(aChipset);
if (uResult == 0)
AssertMsgFailed(("Invalid chipset type %d\n", aChipset));
*count = uResult;
return S_OK;
}
STDMETHODIMP SystemProperties::GetMaxNetworkAdaptersOfType(ChipsetType_T aChipset, NetworkAttachmentType_T aType, ULONG *count)
{
CheckComArgOutPointerValid(count);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.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:
case NetworkAttachmentType_Internal:
case NetworkAttachmentType_NATNetwork:
/* chipset default is OK */
break;
case NetworkAttachmentType_Bridged:
/* Maybe use current host interface count here? */
break;
case NetworkAttachmentType_HostOnly:
uResult = RT_MIN(uResult, 8);
break;
default:
AssertMsgFailed(("Unhandled attachment type %d\n", aType));
}
*count = uResult;
return S_OK;
}
STDMETHODIMP SystemProperties::GetMaxDevicesPerPortForStorageBus(StorageBus_T aBus,
ULONG *aMaxDevicesPerPort)
{
CheckComArgOutPointerValid(aMaxDevicesPerPort);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
switch (aBus)
{
case StorageBus_SATA:
case StorageBus_SCSI:
case StorageBus_SAS:
case StorageBus_USB:
{
/* SATA and both SCSI controllers only support one device per port. */
*aMaxDevicesPerPort = 1;
break;
}
case StorageBus_IDE:
case StorageBus_Floppy:
{
/* The IDE and Floppy controllers support 2 devices. One as master
* and one as slave (or floppy drive 0 and 1). */
*aMaxDevicesPerPort = 2;
break;
}
default:
AssertMsgFailed(("Invalid bus type %d\n", aBus));
}
return S_OK;
}
STDMETHODIMP SystemProperties::GetMinPortCountForStorageBus(StorageBus_T aBus,
ULONG *aMinPortCount)
{
CheckComArgOutPointerValid(aMinPortCount);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
switch (aBus)
{
case StorageBus_SATA:
{
*aMinPortCount = 1;
break;
}
case StorageBus_SCSI:
{
*aMinPortCount = 16;
break;
}
case StorageBus_IDE:
{
*aMinPortCount = 2;
break;
}
case StorageBus_Floppy:
{
*aMinPortCount = 1;
break;
}
case StorageBus_SAS:
case StorageBus_USB:
{
*aMinPortCount = 8;
break;
}
default:
AssertMsgFailed(("Invalid bus type %d\n", aBus));
}
return S_OK;
}
STDMETHODIMP SystemProperties::GetMaxPortCountForStorageBus(StorageBus_T aBus,
ULONG *aMaxPortCount)
{
CheckComArgOutPointerValid(aMaxPortCount);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
switch (aBus)
{
case StorageBus_SATA:
{
*aMaxPortCount = 30;
break;
}
case StorageBus_SCSI:
{
*aMaxPortCount = 16;
break;
}
case StorageBus_IDE:
{
*aMaxPortCount = 2;
break;
}
case StorageBus_Floppy:
{
*aMaxPortCount = 1;
break;
}
case StorageBus_SAS:
case StorageBus_USB:
{
*aMaxPortCount = 8;
break;
}
default:
AssertMsgFailed(("Invalid bus type %d\n", aBus));
}
return S_OK;
}
STDMETHODIMP SystemProperties::GetMaxInstancesOfStorageBus(ChipsetType_T aChipset,
StorageBus_T aBus,
ULONG *aMaxInstances)
{
CheckComArgOutPointerValid(aMaxInstances);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
ULONG cCtrs = 0;
/* no need to lock, this is const */
switch (aBus)
{
case StorageBus_SATA:
case StorageBus_SCSI:
case StorageBus_SAS:
cCtrs = aChipset == ChipsetType_ICH9 ? 8 : 1;
break;
case StorageBus_USB:
case StorageBus_IDE:
case StorageBus_Floppy:
{
cCtrs = 1;
break;
}
default:
AssertMsgFailed(("Invalid bus type %d\n", aBus));
}
*aMaxInstances = cCtrs;
return S_OK;
}
STDMETHODIMP SystemProperties::GetDeviceTypesForStorageBus(StorageBus_T aBus,
ComSafeArrayOut(DeviceType_T, aDeviceTypes))
{
CheckComArgOutSafeArrayPointerValid(aDeviceTypes);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
switch (aBus)
{
case StorageBus_IDE:
case StorageBus_SATA:
case StorageBus_SCSI:
case StorageBus_SAS:
case StorageBus_USB:
{
com::SafeArray<DeviceType_T> saDeviceTypes(2);
saDeviceTypes[0] = DeviceType_DVD;
saDeviceTypes[1] = DeviceType_HardDisk;
saDeviceTypes.detachTo(ComSafeArrayOutArg(aDeviceTypes));
break;
}
case StorageBus_Floppy:
{
com::SafeArray<DeviceType_T> saDeviceTypes(1);
saDeviceTypes[0] = DeviceType_Floppy;
saDeviceTypes.detachTo(ComSafeArrayOutArg(aDeviceTypes));
break;
}
default:
AssertMsgFailed(("Invalid bus type %d\n", aBus));
}
return S_OK;
}
STDMETHODIMP SystemProperties::GetDefaultIoCacheSettingForStorageController(StorageControllerType_T aControllerType, BOOL *aEnabled)
{
CheckComArgOutPointerValid(aEnabled);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
/* no need to lock, this is const */
switch (aControllerType)
{
case StorageControllerType_LsiLogic:
case StorageControllerType_BusLogic:
case StorageControllerType_IntelAhci:
case StorageControllerType_LsiLogicSas:
case StorageControllerType_USB:
*aEnabled = false;
break;
case StorageControllerType_PIIX3:
case StorageControllerType_PIIX4:
case StorageControllerType_ICH6:
case StorageControllerType_I82078:
*aEnabled = true;
break;
default:
AssertMsgFailed(("Invalid controller type %d\n", aControllerType));
}
return S_OK;
}
STDMETHODIMP SystemProperties::GetMaxInstancesOfUSBControllerType(ChipsetType_T aChipset,
USBControllerType_T aType,
ULONG *aMaxInstances)
{
NOREF(aChipset);
CheckComArgOutPointerValid(aMaxInstances);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
ULONG cCtrs = 0;
/* no need to lock, this is const */
switch (aType)
{
case USBControllerType_OHCI:
case USBControllerType_EHCI:
{
cCtrs = 1;
break;
}
default:
AssertMsgFailed(("Invalid bus type %d\n", aType));
}
*aMaxInstances = cCtrs;
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(DefaultMachineFolder)(BSTR *aDefaultMachineFolder)
{
CheckComArgOutPointerValid(aDefaultMachineFolder);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
m->strDefaultMachineFolder.cloneTo(aDefaultMachineFolder);
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(DefaultMachineFolder)(IN_BSTR aDefaultMachineFolder)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = setDefaultMachineFolder(aDefaultMachineFolder);
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(LoggingLevel)(BSTR *aLoggingLevel)
{
CheckComArgOutPointerValid(aLoggingLevel);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
Utf8Str useLoggingLevel(m->strLoggingLevel);
if (useLoggingLevel.isEmpty())
useLoggingLevel = VBOXSVC_LOG_DEFAULT;
useLoggingLevel.cloneTo(aLoggingLevel);
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(LoggingLevel)(IN_BSTR aLoggingLevel)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = setLoggingLevel(aLoggingLevel);
alock.release();
if (SUCCEEDED(rc))
{
AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
rc = mParent->saveSettings();
}
else
LogRel(("Cannot set passed logging level=%ls, or the default one - Error=%Rhrc \n", aLoggingLevel, rc));
return rc;
}
STDMETHODIMP SystemProperties::COMGETTER(MediumFormats)(ComSafeArrayOut(IMediumFormat *, aMediumFormats))
{
CheckComArgOutSafeArrayPointerValid(aMediumFormats);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
SafeIfaceArray<IMediumFormat> mediumFormats(m_llMediumFormats);
mediumFormats.detachTo(ComSafeArrayOutArg(aMediumFormats));
return S_OK;
}
STDMETHODIMP SystemProperties::COMGETTER(DefaultHardDiskFormat)(BSTR *aDefaultHardDiskFormat)
{
CheckComArgOutPointerValid(aDefaultHardDiskFormat);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
m->strDefaultHardDiskFormat.cloneTo(aDefaultHardDiskFormat);
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(DefaultHardDiskFormat)(IN_BSTR aDefaultHardDiskFormat)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = setDefaultHardDiskFormat(aDefaultHardDiskFormat);
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(FreeDiskSpaceWarning)(LONG64 *aFreeSpace)
{
CheckComArgOutPointerValid(aFreeSpace);
ReturnComNotImplemented();
}
STDMETHODIMP SystemProperties::COMSETTER(FreeDiskSpaceWarning)(LONG64 /* aFreeSpace */)
{
ReturnComNotImplemented();
}
STDMETHODIMP SystemProperties::COMGETTER(FreeDiskSpacePercentWarning)(ULONG *aFreeSpacePercent)
{
CheckComArgOutPointerValid(aFreeSpacePercent);
ReturnComNotImplemented();
}
STDMETHODIMP SystemProperties::COMSETTER(FreeDiskSpacePercentWarning)(ULONG /* aFreeSpacePercent */)
{
ReturnComNotImplemented();
}
STDMETHODIMP SystemProperties::COMGETTER(FreeDiskSpaceError)(LONG64 *aFreeSpace)
{
CheckComArgOutPointerValid(aFreeSpace);
ReturnComNotImplemented();
}
STDMETHODIMP SystemProperties::COMSETTER(FreeDiskSpaceError)(LONG64 /* aFreeSpace */)
{
ReturnComNotImplemented();
}
STDMETHODIMP SystemProperties::COMGETTER(FreeDiskSpacePercentError)(ULONG *aFreeSpacePercent)
{
CheckComArgOutPointerValid(aFreeSpacePercent);
ReturnComNotImplemented();
}
STDMETHODIMP SystemProperties::COMSETTER(FreeDiskSpacePercentError)(ULONG /* aFreeSpacePercent */)
{
ReturnComNotImplemented();
}
STDMETHODIMP SystemProperties::COMGETTER(VRDEAuthLibrary)(BSTR *aVRDEAuthLibrary)
{
CheckComArgOutPointerValid(aVRDEAuthLibrary);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
m->strVRDEAuthLibrary.cloneTo(aVRDEAuthLibrary);
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(VRDEAuthLibrary)(IN_BSTR aVRDEAuthLibrary)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = setVRDEAuthLibrary(aVRDEAuthLibrary);
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(WebServiceAuthLibrary)(BSTR *aWebServiceAuthLibrary)
{
CheckComArgOutPointerValid(aWebServiceAuthLibrary);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
m->strWebServiceAuthLibrary.cloneTo(aWebServiceAuthLibrary);
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(WebServiceAuthLibrary)(IN_BSTR aWebServiceAuthLibrary)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = setWebServiceAuthLibrary(aWebServiceAuthLibrary);
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(DefaultVRDEExtPack)(BSTR *aExtPack)
{
CheckComArgOutPointerValid(aExtPack);
AutoCaller autoCaller(this);
HRESULT hrc = autoCaller.rc();
if (SUCCEEDED(hrc))
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
Utf8Str strExtPack(m->strDefaultVRDEExtPack);
if (strExtPack.isNotEmpty())
{
if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
hrc = S_OK;
else
#ifdef VBOX_WITH_EXTPACK
hrc = mParent->getExtPackManager()->checkVrdeExtPack(&strExtPack);
#else
hrc = setError(E_FAIL, tr("The extension pack '%s' does not exist"), strExtPack.c_str());
#endif
}
else
{
#ifdef VBOX_WITH_EXTPACK
hrc = mParent->getExtPackManager()->getDefaultVrdeExtPack(&strExtPack);
#endif
if (strExtPack.isEmpty())
{
/*
* Klugde - check if VBoxVRDP.dll/.so/.dylib is installed.
* This is hardcoded uglyness, sorry.
*/
char szPath[RTPATH_MAX];
int vrc = RTPathAppPrivateArch(szPath, sizeof(szPath));
if (RT_SUCCESS(vrc))
vrc = RTPathAppend(szPath, sizeof(szPath), "VBoxVRDP");
if (RT_SUCCESS(vrc))
vrc = RTStrCat(szPath, sizeof(szPath), RTLdrGetSuff());
if (RT_SUCCESS(vrc) && RTFileExists(szPath))
{
/* Illegal extpack name, so no conflict. */
strExtPack = VBOXVRDP_KLUDGE_EXTPACK_NAME;
}
}
}
if (SUCCEEDED(hrc))
strExtPack.cloneTo(aExtPack);
}
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(DefaultVRDEExtPack)(IN_BSTR aExtPack)
{
CheckComArgNotNull(aExtPack);
Utf8Str strExtPack(aExtPack);
AutoCaller autoCaller(this);
HRESULT hrc = autoCaller.rc();
if (SUCCEEDED(hrc))
{
if (strExtPack.isNotEmpty())
{
if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
hrc = S_OK;
else
#ifdef VBOX_WITH_EXTPACK
hrc = mParent->getExtPackManager()->checkVrdeExtPack(&strExtPack);
#else
hrc = setError(E_FAIL, tr("The extension pack '%s' does not exist"), strExtPack.c_str());
#endif
}
if (SUCCEEDED(hrc))
{
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
hrc = setDefaultVRDEExtPack(aExtPack);
if (SUCCEEDED(hrc))
{
/* VirtualBox::saveSettings() needs the VirtualBox write lock. */
alock.release();
AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
hrc = mParent->saveSettings();
}
}
}
return hrc;
}
STDMETHODIMP SystemProperties::COMGETTER(LogHistoryCount)(ULONG *count)
{
CheckComArgOutPointerValid(count);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
*count = m->ulLogHistoryCount;
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(LogHistoryCount)(ULONG count)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
m->ulLogHistoryCount = count;
alock.release();
// VirtualBox::saveSettings() needs vbox write lock
AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
HRESULT rc = mParent->saveSettings();
return rc;
}
STDMETHODIMP SystemProperties::COMGETTER(DefaultAudioDriver)(AudioDriverType_T *aAudioDriver)
{
CheckComArgOutPointerValid(aAudioDriver);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
*aAudioDriver = settings::MachineConfigFile::getHostDefaultAudioDriver();
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;
}
STDMETHODIMP SystemProperties::COMGETTER(DefaultFrontend)(BSTR *aDefaultFrontend)
{
CheckComArgOutPointerValid(aDefaultFrontend);
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
m->strDefaultFrontend.cloneTo(aDefaultFrontend);
return S_OK;
}
STDMETHODIMP SystemProperties::COMSETTER(DefaultFrontend)(IN_BSTR aDefaultFrontend)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
if (m->strDefaultFrontend == Utf8Str(aDefaultFrontend))
return S_OK;
HRESULT rc = setDefaultFrontend(aDefaultFrontend);
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
/////////////////////////////////////////////////////////////////////////////
HRESULT SystemProperties::loadSettings(const settings::SystemProperties &data)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
HRESULT rc = S_OK;
rc = setDefaultMachineFolder(data.strDefaultMachineFolder);
if (FAILED(rc)) return rc;
rc = setLoggingLevel(data.strLoggingLevel);
if (FAILED(rc)) return rc;
rc = setDefaultHardDiskFormat(data.strDefaultHardDiskFormat);
if (FAILED(rc)) return rc;
rc = setVRDEAuthLibrary(data.strVRDEAuthLibrary);
if (FAILED(rc)) return rc;
rc = setWebServiceAuthLibrary(data.strWebServiceAuthLibrary);
if (FAILED(rc)) return rc;
rc = setDefaultVRDEExtPack(data.strDefaultVRDEExtPack);
if (FAILED(rc)) return rc;
m->ulLogHistoryCount = data.ulLogHistoryCount;
m->fExclusiveHwVirt = data.fExclusiveHwVirt;
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);
}
rc = setDefaultFrontend(data.strDefaultFrontend);
if (FAILED(rc)) return rc;
return S_OK;
}
HRESULT SystemProperties::saveSettings(settings::SystemProperties &data)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
data = *m;
return S_OK;
}
/**
* Returns a medium format object corresponding to the given format
* identifier or null if no such format.
*
* @param aFormat Format identifier.
*
* @return ComObjPtr<MediumFormat>
*/
ComObjPtr<MediumFormat> SystemProperties::mediumFormat(const Utf8Str &aFormat)
{
ComObjPtr<MediumFormat> format;
AutoCaller autoCaller(this);
AssertComRCReturn (autoCaller.rc(), format);
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
for (MediumFormatList::const_iterator it = m_llMediumFormats.begin();
it != m_llMediumFormats.end();
++ it)
{
/* MediumFormat is all const, no need to lock */
if ((*it)->i_getId().compare(aFormat, Utf8Str::CaseInsensitive) == 0)
{
format = *it;
break;
}
}
return format;
}
/**
* Returns a medium format object corresponding to the given file extension or
* null if no such format.
*
* @param aExt File extension.
*
* @return ComObjPtr<MediumFormat>
*/
ComObjPtr<MediumFormat> SystemProperties::mediumFormatFromExtension(const Utf8Str &aExt)
{
ComObjPtr<MediumFormat> format;
AutoCaller autoCaller(this);
AssertComRCReturn (autoCaller.rc(), format);
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
bool fFound = false;
for (MediumFormatList::const_iterator it = m_llMediumFormats.begin();
it != m_llMediumFormats.end() && !fFound;
++it)
{
/* MediumFormat is all const, no need to lock */
MediumFormat::StrArray aFileList = (*it)->i_getFileExtensions();
for (MediumFormat::StrArray::const_iterator it1 = aFileList.begin();
it1 != aFileList.end();
++it1)
{
if ((*it1).compare(aExt, Utf8Str::CaseInsensitive) == 0)
{
format = *it;
fFound = true;
break;
}
}
}
return format;
}
// private methods
/////////////////////////////////////////////////////////////////////////////
/**
* Returns the user's home directory. Wrapper around RTPathUserHome().
* @param strPath
* @return
*/
HRESULT SystemProperties::getUserHomeDirectory(Utf8Str &strPath)
{
char szHome[RTPATH_MAX];
int vrc = RTPathUserHome(szHome, sizeof(szHome));
if (RT_FAILURE(vrc))
return setError(E_FAIL,
tr("Cannot determine user home directory (%Rrc)"),
vrc);
strPath = szHome;
return S_OK;
}
/**
* Internal implementation to set the default machine folder. Gets called
* from the public attribute setter as well as loadSettings(). With 4.0,
* the "default default" machine folder has changed, and we now require
* a full path always.
* @param aPath
* @return
*/
HRESULT SystemProperties::setDefaultMachineFolder(const Utf8Str &strPath)
{
Utf8Str path(strPath); // make modifiable
if ( path.isEmpty() // used by API calls to reset the default
|| path == "Machines" // this value (exactly like this, without path) is stored
// in VirtualBox.xml if user upgrades from before 4.0 and
// has not changed the default machine folder
)
{
// new default with VirtualBox 4.0: "$HOME/VirtualBox VMs"
HRESULT rc = getUserHomeDirectory(path);
if (FAILED(rc)) return rc;
path += RTPATH_SLASH_STR "VirtualBox VMs";
}
if (!RTPathStartsWithRoot(path.c_str()))
return setError(E_INVALIDARG,
tr("Given default machine folder '%s' is not fully qualified"),
path.c_str());
m->strDefaultMachineFolder = path;
return S_OK;
}
HRESULT SystemProperties::setLoggingLevel(const Utf8Str &aLoggingLevel)
{
Utf8Str useLoggingLevel(aLoggingLevel);
int rc = RTLogGroupSettings(RTLogRelDefaultInstance(), useLoggingLevel.c_str());
// If failed and not the default logging level - try to use the default logging level.
if (RT_FAILURE(rc))
{
// If failed write message to the release log.
LogRel(("Cannot set passed logging level=%s Error=%Rrc \n", useLoggingLevel.c_str(), rc));
// If attempted logging level not the default one then try the default one.
if (!useLoggingLevel.equals(VBOXSVC_LOG_DEFAULT))
{
rc = RTLogGroupSettings(RTLogRelDefaultInstance(), VBOXSVC_LOG_DEFAULT);
// If failed report this to the release log.
if (RT_FAILURE(rc))
LogRel(("Cannot set default logging level Error=%Rrc \n", rc));
}
// On any failure - set default level as the one to be stored.
useLoggingLevel = VBOXSVC_LOG_DEFAULT;
}
// Set to passed value or if default used/attempted (even if error condition) use empty string.
m->strLoggingLevel = (useLoggingLevel.equals(VBOXSVC_LOG_DEFAULT) ? "" : useLoggingLevel);
return RT_SUCCESS(rc) ? S_OK : E_FAIL;
}
HRESULT SystemProperties::setDefaultHardDiskFormat(const Utf8Str &aFormat)
{
if (!aFormat.isEmpty())
m->strDefaultHardDiskFormat = aFormat;
else
m->strDefaultHardDiskFormat = "VDI";
return S_OK;
}
HRESULT SystemProperties::setVRDEAuthLibrary(const Utf8Str &aPath)
{
if (!aPath.isEmpty())
m->strVRDEAuthLibrary = aPath;
else
m->strVRDEAuthLibrary = "VBoxAuth";
return S_OK;
}
HRESULT SystemProperties::setWebServiceAuthLibrary(const Utf8Str &aPath)
{
if (!aPath.isEmpty())
m->strWebServiceAuthLibrary = aPath;
else
m->strWebServiceAuthLibrary = "VBoxAuth";
return S_OK;
}
HRESULT SystemProperties::setDefaultVRDEExtPack(const Utf8Str &aExtPack)
{
m->strDefaultVRDEExtPack = 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;
}
HRESULT SystemProperties::setDefaultFrontend(const Utf8Str &aDefaultFrontend)
{
m->strDefaultFrontend = aDefaultFrontend;
return S_OK;
}