summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-server/MachineImpl.cpp
diff options
context:
space:
mode:
authorFelix Geyer <fgeyer@debian.org>2013-03-02 22:29:33 +0100
committerFelix Geyer <fgeyer@debian.org>2013-03-02 22:29:33 +0100
commitfb32dd2be67519662e93ffbbe520c79d95b1fbfb (patch)
treee445911bff35c842af26b5e5c0ee31573be49008 /src/VBox/Main/src-server/MachineImpl.cpp
parent490244144bf10ecd165f2f81f2c88b7781c91d85 (diff)
downloadvirtualbox-upstream/4.2.8-dfsg.tar.gz
Imported Upstream version 4.2.8-dfsgupstream/4.2.8-dfsg
Diffstat (limited to 'src/VBox/Main/src-server/MachineImpl.cpp')
-rw-r--r--src/VBox/Main/src-server/MachineImpl.cpp274
1 files changed, 160 insertions, 114 deletions
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index 100f696e6..2086e3e29 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2004-2012 Oracle Corporation
+ * Copyright (C) 2004-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;
@@ -208,6 +208,7 @@ Machine::HWData::HWData()
mKeyboardHIDType = KeyboardHIDType_PS2Keyboard;
mPointingHIDType = PointingHIDType_PS2Mouse;
mChipsetType = ChipsetType_PIIX3;
+ mEmulatedUSBWebcamEnabled = FALSE;
mEmulatedUSBCardReaderEnabled = FALSE;
for (size_t i = 0; i < RT_ELEMENTS(mCPUAttached); i++)
@@ -1622,14 +1623,42 @@ STDMETHODIMP Machine::COMSETTER(EmulatedUSBCardReaderEnabled)(BOOL enabled)
STDMETHODIMP Machine::COMGETTER(EmulatedUSBWebcameraEnabled)(BOOL *enabled)
{
+#ifdef VBOX_WITH_USB_VIDEO
+ CheckComArgOutPointerValid(enabled);
+
+ AutoCaller autoCaller(this);
+ if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+ AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+ *enabled = mHWData->mEmulatedUSBWebcamEnabled;
+
+ return S_OK;
+#else
NOREF(enabled);
return E_NOTIMPL;
+#endif
}
STDMETHODIMP Machine::COMSETTER(EmulatedUSBWebcameraEnabled)(BOOL enabled)
{
+#ifdef VBOX_WITH_USB_VIDEO
+ 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;
+
+ setModified(IsModified_MachineData);
+ mHWData.backup();
+ mHWData->mEmulatedUSBWebcamEnabled = enabled;
+
+ return S_OK;
+#else
NOREF(enabled);
return E_NOTIMPL;
+#endif
}
STDMETHODIMP Machine::COMGETTER(HPETEnabled)(BOOL *enabled)
@@ -5441,21 +5470,18 @@ HRESULT Machine::getGuestPropertyFromService(IN_BSTR aName,
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
Utf8Str strName(aName);
- HWData::GuestPropertyList::const_iterator it;
+ HWData::GuestPropertyMap::const_iterator it =
+ mHWData->mGuestProperties.find(strName);
- for (it = mHWData->mGuestProperties.begin();
- it != mHWData->mGuestProperties.end(); ++it)
+ if (it != mHWData->mGuestProperties.end())
{
- if (it->strName == strName)
- {
- char szFlags[MAX_FLAGS_LEN + 1];
- it->strValue.cloneTo(aValue);
- *aTimestamp = it->mTimestamp;
- writeFlags(it->mFlags, szFlags);
- Bstr(szFlags).cloneTo(aFlags);
- break;
- }
+ char szFlags[MAX_FLAGS_LEN + 1];
+ it->second.strValue.cloneTo(aValue);
+ *aTimestamp = it->second.mTimestamp;
+ writeFlags(it->second.mFlags, szFlags);
+ Bstr(szFlags).cloneTo(aFlags);
}
+
return S_OK;
}
@@ -5538,7 +5564,6 @@ HRESULT Machine::setGuestPropertyToService(IN_BSTR aName, IN_BSTR aValue,
HRESULT rc = S_OK;
HWData::GuestProperty property;
property.mFlags = NILFLAG;
- bool found = false;
rc = checkStateDependency(MutableStateDep);
if (FAILED(rc)) return rc;
@@ -5548,64 +5573,62 @@ HRESULT Machine::setGuestPropertyToService(IN_BSTR aName, IN_BSTR aValue,
Utf8Str utf8Name(aName);
Utf8Str utf8Flags(aFlags);
uint32_t fFlags = NILFLAG;
- if ( (aFlags != NULL)
- && RT_FAILURE(validateFlags(utf8Flags.c_str(), &fFlags))
+ if ( (aFlags != NULL)
+ && RT_FAILURE(validateFlags(utf8Flags.c_str(), &fFlags))
)
return setError(E_INVALIDARG,
- tr("Invalid flag values: '%ls'"),
+ tr("Invalid guest property flag values: '%ls'"),
aFlags);
- /** @todo r=bird: see efficiency rant in PushGuestProperty. (Yeah, I
- * know, this is simple and do an OK job atm.) */
- HWData::GuestPropertyList::iterator it;
- for (it = mHWData->mGuestProperties.begin();
- it != mHWData->mGuestProperties.end(); ++it)
- if (it->strName == utf8Name)
+ HWData::GuestPropertyMap::iterator it =
+ mHWData->mGuestProperties.find(utf8Name);
+
+ if (it == mHWData->mGuestProperties.end())
+ {
+ setModified(IsModified_MachineData);
+ mHWData.backupEx();
+
+ RTTIMESPEC time;
+ HWData::GuestProperty prop;
+ prop.strValue = aValue;
+ prop.mTimestamp = RTTimeSpecGetNano(RTTimeNow(&time));
+ prop.mFlags = fFlags;
+
+ mHWData->mGuestProperties[Utf8Str(aName)] = prop;
+ }
+ else
+ {
+ if (it->second.mFlags & (RDONLYHOST))
{
- property = *it;
- if (it->mFlags & (RDONLYHOST))
- rc = setError(E_ACCESSDENIED,
- tr("The property '%ls' cannot be changed by the host"),
- aName);
+ rc = setError(E_ACCESSDENIED,
+ tr("The property '%ls' cannot be changed by the host"),
+ aName);
+ }
+ else
+ {
+ setModified(IsModified_MachineData);
+ mHWData.backupEx();
+
+ /* The backupEx() operation invalidates our iterator,
+ * so get a new one. */
+ it = mHWData->mGuestProperties.find(utf8Name);
+ Assert(it != mHWData->mGuestProperties.end());
+
+ if (RT_VALID_PTR(aValue) && *(aValue) != '\0')
+ {
+ RTTIMESPEC time;
+ it->second.strValue = aValue;
+ it->second.mTimestamp = RTTimeSpecGetNano(RTTimeNow(&time));
+ if (aFlags != NULL)
+ it->second.mFlags = fFlags;
+ }
else
{
- setModified(IsModified_MachineData);
- mHWData.backup(); // @todo r=dj backup in a loop?!?
-
- /* The backup() operation invalidates our iterator, so
- * get a new one. */
- for (it = mHWData->mGuestProperties.begin();
- it->strName != utf8Name;
- ++it)
- ;
mHWData->mGuestProperties.erase(it);
}
- found = true;
- break;
}
- if (found && SUCCEEDED(rc))
- {
- if (aValue)
- {
- RTTIMESPEC time;
- property.strValue = aValue;
- property.mTimestamp = RTTimeSpecGetNano(RTTimeNow(&time));
- if (aFlags != NULL)
- property.mFlags = fFlags;
- mHWData->mGuestProperties.push_back(property);
- }
- }
- else if (SUCCEEDED(rc) && aValue)
- {
- RTTIMESPEC time;
- setModified(IsModified_MachineData);
- mHWData.backup();
- property.strName = aName;
- property.strValue = aValue;
- property.mTimestamp = RTTimeSpecGetNano(RTTimeNow(&time));
- property.mFlags = fFlags;
- mHWData->mGuestProperties.push_back(property);
}
+
if ( SUCCEEDED(rc)
&& ( mHWData->mGuestPropertyNotificationPatterns.isEmpty()
|| RTStrSimplePatternMultiMatch(mHWData->mGuestPropertyNotificationPatterns.c_str(),
@@ -5616,8 +5639,8 @@ HRESULT Machine::setGuestPropertyToService(IN_BSTR aName, IN_BSTR aValue,
)
)
{
- /** @todo r=bird: Why aren't we leaving the lock here? The
- * same code in PushGuestProperty does... */
+ alock.release();
+
mParent->onGuestPropertyChange(mData->mUuid, aName,
aValue ? aValue : Bstr("").raw(),
aFlags ? aFlags : Bstr("").raw());
@@ -5713,42 +5736,50 @@ HRESULT Machine::enumerateGuestPropertiesInService
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
Utf8Str strPatterns(aPatterns);
+ HWData::GuestPropertyMap propMap;
+
/*
* Look for matching patterns and build up a list.
*/
- HWData::GuestPropertyList propList;
- for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin();
- it != mHWData->mGuestProperties.end();
- ++it)
+ HWData::GuestPropertyMap::const_iterator it = mHWData->mGuestProperties.begin();
+ while (it != mHWData->mGuestProperties.end())
+ {
if ( strPatterns.isEmpty()
|| RTStrSimplePatternMultiMatch(strPatterns.c_str(),
RTSTR_MAX,
- it->strName.c_str(),
+ it->first.c_str(),
RTSTR_MAX,
NULL)
)
- propList.push_back(*it);
+ {
+ propMap.insert(*it);
+ }
+
+ it++;
+ }
+
+ alock.release();
/*
* And build up the arrays for returning the property information.
*/
- size_t cEntries = propList.size();
+ size_t cEntries = propMap.size();
SafeArray<BSTR> names(cEntries);
SafeArray<BSTR> values(cEntries);
SafeArray<LONG64> timestamps(cEntries);
SafeArray<BSTR> flags(cEntries);
size_t iProp = 0;
- for (HWData::GuestPropertyList::iterator it = propList.begin();
- it != propList.end();
- ++it)
+
+ it = propMap.begin();
+ while (it != propMap.end())
{
char szFlags[MAX_FLAGS_LEN + 1];
- it->strName.cloneTo(&names[iProp]);
- it->strValue.cloneTo(&values[iProp]);
- timestamps[iProp] = it->mTimestamp;
- writeFlags(it->mFlags, szFlags);
- Bstr(szFlags).cloneTo(&flags[iProp]);
- ++iProp;
+ it->first.cloneTo(&names[iProp]);
+ it->second.strValue.cloneTo(&values[iProp]);
+ timestamps[iProp] = it->second.mTimestamp;
+ writeFlags(it->second.mFlags, szFlags);
+ Bstr(szFlags).cloneTo(&flags[iProp++]);
+ it++;
}
names.detachTo(ComSafeArrayOutArg(aNames));
values.detachTo(ComSafeArrayOutArg(aValues));
@@ -8530,6 +8561,7 @@ HRESULT Machine::loadHardware(const settings::Hardware &data, const settings::De
mHWData->mPointingHIDType = data.pointingHIDType;
mHWData->mKeyboardHIDType = data.keyboardHIDType;
mHWData->mChipsetType = data.chipsetType;
+ mHWData->mEmulatedUSBWebcamEnabled = data.fEmulatedUSBWebcam;
mHWData->mEmulatedUSBCardReaderEnabled = data.fEmulatedUSBCardReader;
mHWData->mHPETEnabled = data.fHPETEnabled;
@@ -8671,8 +8703,8 @@ HRESULT Machine::loadHardware(const settings::Hardware &data, const settings::De
const settings::GuestProperty &prop = *it;
uint32_t fFlags = guestProp::NILFLAG;
guestProp::validateFlags(prop.strFlags.c_str(), &fFlags);
- HWData::GuestProperty property = { prop.strName, prop.strValue, (LONG64) prop.timestamp, fFlags };
- mHWData->mGuestProperties.push_back(property);
+ HWData::GuestProperty property = { prop.strValue, (LONG64) prop.timestamp, fFlags };
+ mHWData->mGuestProperties[prop.strName] = property;
}
mHWData->mGuestPropertyNotificationPatterns = data.strNotificationPatterns;
@@ -9715,6 +9747,7 @@ HRESULT Machine::saveHardware(settings::Hardware &data, settings::Debugging *pDb
// chipset
data.chipsetType = mHWData->mChipsetType;
+ data.fEmulatedUSBWebcam = !!mHWData->mEmulatedUSBWebcamEnabled;
data.fEmulatedUSBCardReader = !!mHWData->mEmulatedUSBCardReaderEnabled;
// HPET
@@ -9854,11 +9887,11 @@ HRESULT Machine::saveHardware(settings::Hardware &data, settings::Debugging *pDb
// guest properties
data.llGuestProperties.clear();
#ifdef VBOX_WITH_GUEST_PROPS
- for (HWData::GuestPropertyList::const_iterator it = mHWData->mGuestProperties.begin();
+ for (HWData::GuestPropertyMap::const_iterator it = mHWData->mGuestProperties.begin();
it != mHWData->mGuestProperties.end();
++it)
{
- HWData::GuestProperty property = *it;
+ HWData::GuestProperty property = it->second;
/* Remove transient guest properties at shutdown unless we
* are saving state */
@@ -9869,7 +9902,7 @@ HRESULT Machine::saveHardware(settings::Hardware &data, settings::Debugging *pDb
|| property.mFlags & guestProp::TRANSRESET))
continue;
settings::GuestProperty prop;
- prop.strName = property.strName;
+ prop.strName = it->first;
prop.strValue = property.strValue;
prop.timestamp = property.mTimestamp;
char szFlags[guestProp::MAX_FLAGS_LEN + 1];
@@ -10372,6 +10405,30 @@ HRESULT Machine::deleteImplicitDiffs(bool aOnline)
/* We absolutely must have backed up state. */
AssertReturn(mMediaData.isBackedUp(), E_FAIL);
+ /* Check if there are any implicitly created diff images. */
+ bool fImplicitDiffs = false;
+ for (MediaData::AttachmentList::const_iterator it = mMediaData->mAttachments.begin();
+ it != mMediaData->mAttachments.end();
+ ++it)
+ {
+ const ComObjPtr<MediumAttachment> &pAtt = *it;
+ if (pAtt->isImplicit())
+ {
+ fImplicitDiffs = true;
+ break;
+ }
+ }
+ /* If there is nothing to do, leave early. This saves lots of image locking
+ * effort. It also avoids a MachineStateChanged event without real reason.
+ * This is important e.g. when loading a VM config, because there should be
+ * no events. Otherwise API clients can become thoroughly confused for
+ * inaccessible VMs (the code for loading VM configs uses this method for
+ * cleanup if the config makes no sense), as they take such events as an
+ * indication that the VM is alive, and they would force the VM config to
+ * be reread, leading to an endless loop. */
+ if (!fImplicitDiffs)
+ return S_OK;
+
HRESULT rc = S_OK;
MachineState_T oldState = mData->mMachineState;
@@ -12742,18 +12799,18 @@ STDMETHODIMP SessionMachine::PullGuestProperties(ComSafeArrayOut(BSTR, aNames),
com::SafeArray<LONG64> timestamps(cEntries);
com::SafeArray<BSTR> flags(cEntries);
unsigned i = 0;
- for (HWData::GuestPropertyList::iterator it = mHWData->mGuestProperties.begin();
+ for (HWData::GuestPropertyMap::iterator it = mHWData->mGuestProperties.begin();
it != mHWData->mGuestProperties.end();
++it)
{
char szFlags[MAX_FLAGS_LEN + 1];
- it->strName.cloneTo(&names[i]);
- it->strValue.cloneTo(&values[i]);
- timestamps[i] = it->mTimestamp;
+ it->first.cloneTo(&names[i]);
+ it->second.strValue.cloneTo(&values[i]);
+ timestamps[i] = it->second.mTimestamp;
/* If it is NULL, keep it NULL. */
- if (it->mFlags)
+ if (it->second.mFlags)
{
- writeFlags(it->mFlags, szFlags);
+ writeFlags(it->second.mFlags, szFlags);
Bstr(szFlags).cloneTo(&flags[i]);
}
else
@@ -12830,29 +12887,18 @@ STDMETHODIMP SessionMachine::PushGuestProperty(IN_BSTR aName,
setModified(IsModified_MachineData);
mHWData.backup();
- /** @todo r=bird: The careful memory handling doesn't work out here because
- * the catch block won't undo any damage we've done. So, if push_back throws
- * bad_alloc then you've lost the value.
- *
- * Another thing. Doing a linear search here isn't extremely efficient, esp.
- * since values that changes actually bubbles to the end of the list. Using
- * something that has an efficient lookup and can tolerate a bit of updates
- * would be nice. RTStrSpace is one suggestion (it's not perfect). Some
- * combination of RTStrCache (for sharing names and getting uniqueness into
- * the bargain) and hash/tree is another. */
- for (HWData::GuestPropertyList::iterator iter = mHWData->mGuestProperties.begin();
- iter != mHWData->mGuestProperties.end();
- ++iter)
- if (utf8Name == iter->strName)
+ HWData::GuestPropertyMap::iterator it = mHWData->mGuestProperties.find(utf8Name);
+ if (it != mHWData->mGuestProperties.end())
+ {
+ if (RT_VALID_PTR(aValue) && *(aValue) != '\0')
{
- mHWData->mGuestProperties.erase(iter);
- mData->mGuestPropertiesModified = TRUE;
- break;
+ it->second.strValue = aValue;
+ it->second.mFlags = fFlags;
+ it->second.mTimestamp = aTimestamp;
}
- if (aValue != NULL)
- {
- HWData::GuestProperty property = { aName, aValue, aTimestamp, fFlags };
- mHWData->mGuestProperties.push_back(property);
+ else
+ mHWData->mGuestProperties.erase(it);
+
mData->mGuestPropertiesModified = TRUE;
}
@@ -13918,13 +13964,13 @@ HRESULT SessionMachine::setMachineState(MachineState_T aMachineState)
/* Make sure any transient guest properties get removed from the
* property store on shutdown. */
- HWData::GuestPropertyList::iterator it;
+ HWData::GuestPropertyMap::const_iterator it;
BOOL fNeedsSaving = mData->mGuestPropertiesModified;
if (!fNeedsSaving)
for (it = mHWData->mGuestProperties.begin();
it != mHWData->mGuestProperties.end(); ++it)
- if ( (it->mFlags & guestProp::TRANSIENT)
- || (it->mFlags & guestProp::TRANSRESET))
+ if ( (it->second.mFlags & guestProp::TRANSIENT)
+ || (it->second.mFlags & guestProp::TRANSRESET))
{
fNeedsSaving = true;
break;