summaryrefslogtreecommitdiff
path: root/src/VBox/Main
diff options
context:
space:
mode:
authorFelix Geyer <fgeyer@debian.org>2014-04-05 22:17:15 +0200
committerFelix Geyer <fgeyer@debian.org>2014-04-05 22:17:15 +0200
commit1700c7d32f7d9d101cbba9f1fcb8bb57ed16a727 (patch)
tree727251ad65172262944f82bb0f28601c3fb6f6b3 /src/VBox/Main
parent1e85aed889b772c2f2daa7a6d9e8bd967aa213d8 (diff)
downloadvirtualbox-upstream.tar.gz
Imported Upstream version 4.3.10-dfsgupstream/4.3.10-dfsgupstream
Diffstat (limited to 'src/VBox/Main')
-rw-r--r--src/VBox/Main/include/ApplianceImpl.h1
-rw-r--r--src/VBox/Main/include/ConsoleImpl.h10
-rw-r--r--src/VBox/Main/include/DisplayImpl.h12
-rw-r--r--src/VBox/Main/include/EventImpl.h2
-rw-r--r--src/VBox/Main/include/MachineImpl.h2
-rw-r--r--src/VBox/Main/src-all/EventImpl.cpp420
-rw-r--r--src/VBox/Main/src-client/ConsoleImpl.cpp708
-rw-r--r--src/VBox/Main/src-client/ConsoleImpl2.cpp8
-rw-r--r--src/VBox/Main/src-client/DisplayImpl.cpp77
-rw-r--r--src/VBox/Main/src-client/GuestFileImpl.cpp2
-rw-r--r--src/VBox/Main/src-client/GuestImpl.cpp2
-rw-r--r--src/VBox/Main/src-client/GuestProcessImpl.cpp2
-rw-r--r--src/VBox/Main/src-client/GuestSessionImpl.cpp2
-rw-r--r--src/VBox/Main/src-client/KeyboardImpl.cpp2
-rw-r--r--src/VBox/Main/src-client/MouseImpl.cpp2
-rw-r--r--src/VBox/Main/src-client/VirtualBoxClientImpl.cpp2
-rw-r--r--src/VBox/Main/src-server/ApplianceImpl.cpp2
-rw-r--r--src/VBox/Main/src-server/ApplianceImplExport.cpp17
-rw-r--r--src/VBox/Main/src-server/HostDnsService.cpp4
-rw-r--r--src/VBox/Main/src-server/MachineImpl.cpp90
-rw-r--r--src/VBox/Main/src-server/NATNetworkImpl.cpp4
-rw-r--r--src/VBox/Main/src-server/VirtualBoxImpl.cpp8
-rw-r--r--src/VBox/Main/src-server/darwin/iokit.cpp4
23 files changed, 661 insertions, 722 deletions
diff --git a/src/VBox/Main/include/ApplianceImpl.h b/src/VBox/Main/include/ApplianceImpl.h
index 7080d14c2..937ebbfd1 100644
--- a/src/VBox/Main/include/ApplianceImpl.h
+++ b/src/VBox/Main/include/ApplianceImpl.h
@@ -264,6 +264,7 @@ struct VirtualSystemDescriptionEntry
Utf8Str strExtraConfigCurrent; // extra configuration key=value strings (type-dependent); current value, either from interpret() or setFinalValue()
uint32_t ulSizeMB; // hard disk images only: a copy of ovf::DiskImage::ulSuggestedSizeMB
+ bool skipIt; ///< used during export to skip some parts if it's needed
};
class ATL_NO_VTABLE VirtualSystemDescription :
diff --git a/src/VBox/Main/include/ConsoleImpl.h b/src/VBox/Main/include/ConsoleImpl.h
index 220ff7bc3..5e5cb6965 100644
--- a/src/VBox/Main/include/ConsoleImpl.h
+++ b/src/VBox/Main/include/ConsoleImpl.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2005-2013 Oracle Corporation
+ * Copyright (C) 2005-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -540,6 +540,9 @@ private:
HRESULT createSharedFolder(const Utf8Str &strName, const SharedFolderData &aData);
HRESULT removeSharedFolder(const Utf8Str &strName);
+ HRESULT suspendBeforeConfigChange(PUVM pUVM, AutoWriteLock *pAlock, bool *pfResume);
+ void resumeAfterConfigChange(PUVM pUVM);
+
static DECLCALLBACK(int) configConstructor(PUVM pUVM, PVM pVM, void *pvConsole);
int configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock);
int configCfgmOverlay(PCFGMNODE pRoot, IVirtualBox *pVirtualBox, IMachine *pMachine);
@@ -567,7 +570,8 @@ private:
bool fForceUnmount,
bool fHotplug,
PUVM pUVM,
- DeviceType_T *paLedDevType);
+ DeviceType_T *paLedDevType,
+ PCFGMNODE *ppLunL0);
int configMedium(PCFGMNODE pLunL0,
bool fPassthrough,
DeviceType_T enmType,
@@ -581,7 +585,7 @@ private:
IMedium *pMedium,
MachineState_T aMachineState,
HRESULT *phrc);
- static DECLCALLBACK(int) reconfigureMediumAttachment(Console *pConsole,
+ static DECLCALLBACK(int) reconfigureMediumAttachment(Console *pThis,
PUVM pUVM,
const char *pcszDevice,
unsigned uInstance,
diff --git a/src/VBox/Main/include/DisplayImpl.h b/src/VBox/Main/include/DisplayImpl.h
index b1239ca43..4bc1415a4 100644
--- a/src/VBox/Main/include/DisplayImpl.h
+++ b/src/VBox/Main/include/DisplayImpl.h
@@ -166,14 +166,15 @@ public:
int handleVHWACommandProcess(PVBOXVHWACMD pCommand);
#endif
#ifdef VBOX_WITH_CRHGSMI
- int handleCrCmdNotifyCmds();
void handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
void handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl);
void handleCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
void handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
#endif
-
+ int handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
+ PFNCRCTLCOMPLETION pfnCompletion,
+ void *pvCompletion);
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
void handleCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam);
void handleCrVRecScreenshotPerform(uint32_t uScreen,
@@ -264,14 +265,17 @@ private:
#endif
#ifdef VBOX_WITH_CRHGSMI
- static DECLCALLBACK(int) displayCrCmdNotifyCmds(PPDMIDISPLAYCONNECTOR pInterface);
static DECLCALLBACK(void) displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd);
static DECLCALLBACK(void) displayCrHgsmiControlProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl);
static DECLCALLBACK(void) displayCrHgsmiCommandCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
static DECLCALLBACK(void) displayCrHgsmiControlCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
#endif
-
+ static DECLCALLBACK(int) displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface,
+ struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
+ PFNCRCTLCOMPLETION pfnCompletion,
+ void *pvCompletion);
+ static DECLCALLBACK(void) displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext);
#ifdef VBOX_WITH_HGSMI
static DECLCALLBACK(int) displayVBVAEnable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags);
static DECLCALLBACK(void) displayVBVADisable(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId);
diff --git a/src/VBox/Main/include/EventImpl.h b/src/VBox/Main/include/EventImpl.h
index e2979ce64..414ce013a 100644
--- a/src/VBox/Main/include/EventImpl.h
+++ b/src/VBox/Main/include/EventImpl.h
@@ -144,7 +144,7 @@ public:
void FinalRelease();
// public initializer/uninitializer for internal purposes only
- HRESULT init(IUnknown *aParent);
+ HRESULT init();
void uninit();
// IEventSource methods
diff --git a/src/VBox/Main/include/MachineImpl.h b/src/VBox/Main/include/MachineImpl.h
index cea78f32a..0ad426594 100644
--- a/src/VBox/Main/include/MachineImpl.h
+++ b/src/VBox/Main/include/MachineImpl.h
@@ -1219,6 +1219,8 @@ private:
/** client token for this machine */
ClientToken *mClientToken;
+ int miNATNetworksStarted;
+
static DECLCALLBACK(int) taskHandler(RTTHREAD thread, void *pvUser);
};
diff --git a/src/VBox/Main/src-all/EventImpl.cpp b/src/VBox/Main/src-all/EventImpl.cpp
index 0d19c3bdb..820f84b93 100644
--- a/src/VBox/Main/src-all/EventImpl.cpp
+++ b/src/VBox/Main/src-all/EventImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010-2012 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -120,7 +120,7 @@ HRESULT VBoxEvent::init(IEventSource *aSource, VBoxEventType_T aType, BOOL aWait
if (RT_FAILURE(vrc))
{
- AssertFailed ();
+ AssertFailed();
return setError(E_FAIL,
tr("Internal error (%Rrc)"), vrc);
}
@@ -155,19 +155,21 @@ STDMETHODIMP VBoxEvent::COMGETTER(Type)(VBoxEventType_T *aType)
CheckComArgNotNull(aType);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
- // never changes till event alive, no locking?
+ // never changes while event alive, no locking
*aType = m->mType;
return S_OK;
}
-STDMETHODIMP VBoxEvent::COMGETTER(Source)(IEventSource* *aSource)
+STDMETHODIMP VBoxEvent::COMGETTER(Source)(IEventSource **aSource)
{
CheckComArgOutPointerValid(aSource);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
m->mSource.queryInterfaceTo(aSource);
return S_OK;
@@ -178,9 +180,10 @@ STDMETHODIMP VBoxEvent::COMGETTER(Waitable)(BOOL *aWaitable)
CheckComArgNotNull(aWaitable);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
- // never changes till event alive, no locking?
+ // never changes while event alive, no locking
*aWaitable = m->mWaitable;
return S_OK;
}
@@ -189,7 +192,8 @@ STDMETHODIMP VBoxEvent::COMGETTER(Waitable)(BOOL *aWaitable)
STDMETHODIMP VBoxEvent::SetProcessed()
{
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -209,7 +213,8 @@ STDMETHODIMP VBoxEvent::WaitProcessed(LONG aTimeout, BOOL *aResult)
CheckComArgNotNull(aResult);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
{
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -249,8 +254,7 @@ STDMETHODIMP VBoxEvent::WaitProcessed(LONG aTimeout, BOOL *aResult)
typedef std::list<Bstr> VetoList;
struct VBoxVetoEvent::Data
{
- Data()
- :
+ Data() :
mVetoed(FALSE)
{}
BOOL mVetoed;
@@ -281,7 +285,8 @@ HRESULT VBoxVetoEvent::init(IEventSource *aSource, VBoxEventType_T aType)
HRESULT rc = S_OK;
// all veto events are waitable
rc = VBoxEvent::init(aSource, aType, TRUE);
- if (FAILED(rc)) return rc;
+ if (FAILED(rc))
+ return rc;
m->mVetoed = FALSE;
m->mVetoList.clear();
@@ -300,7 +305,8 @@ void VBoxVetoEvent::uninit()
STDMETHODIMP VBoxVetoEvent::AddVeto(IN_BSTR aVeto)
{
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -312,12 +318,13 @@ STDMETHODIMP VBoxVetoEvent::AddVeto(IN_BSTR aVeto)
return S_OK;
}
-STDMETHODIMP VBoxVetoEvent::IsVetoed(BOOL * aResult)
+STDMETHODIMP VBoxVetoEvent::IsVetoed(BOOL *aResult)
{
CheckComArgOutPointerValid(aResult);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -326,13 +333,14 @@ STDMETHODIMP VBoxVetoEvent::IsVetoed(BOOL * aResult)
return S_OK;
}
-STDMETHODIMP VBoxVetoEvent::GetVetos(ComSafeArrayOut(BSTR, aVetos))
+STDMETHODIMP VBoxVetoEvent::GetVetos(ComSafeArrayOut(BSTR, aVetos))
{
if (ComSafeArrayOutIsNull(aVetos))
return E_POINTER;
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
com::SafeArray<BSTR> vetos(m->mVetoList.size());
@@ -351,8 +359,8 @@ STDMETHODIMP VBoxVetoEvent::GetVetos(ComSafeArrayOut(BSTR, aVetos))
}
static const int FirstEvent = (int)VBoxEventType_LastWildcard + 1;
-static const int LastEvent = (int)VBoxEventType_Last;
-static const int NumEvents = LastEvent - FirstEvent;
+static const int LastEvent = (int)VBoxEventType_Last;
+static const int NumEvents = LastEvent - FirstEvent;
/**
* Class replacing std::list and able to provide required stability
@@ -367,24 +375,19 @@ public:
* We have to be double linked, as structural modifications in list are delayed
* till element removed, so we have to know our previous one to update its next
*/
- EventMapRecord* mNext;
+ EventMapRecord *mNext;
bool mAlive;
private:
- EventMapRecord* mPrev;
- ListenerRecord* mRef; /* must be weak reference */
+ EventMapRecord *mPrev;
+ ListenerRecord *mRef; /* must be weak reference */
int32_t mRefCnt;
public:
- EventMapRecord(ListenerRecord* aRef)
- :
- mNext(0),
- mAlive(true),
- mPrev(0),
- mRef(aRef),
- mRefCnt(1)
+ EventMapRecord(ListenerRecord *aRef) :
+ mNext(0), mAlive(true), mPrev(0), mRef(aRef), mRefCnt(1)
{}
- EventMapRecord(EventMapRecord& aOther)
+ EventMapRecord(EventMapRecord &aOther)
{
mNext = aOther.mNext;
mPrev = aOther.mPrev;
@@ -408,7 +411,8 @@ public:
void release()
{
- if (ASMAtomicDecS32(&mRefCnt) <= 0) delete this;
+ if (ASMAtomicDecS32(&mRefCnt) <= 0)
+ delete this;
}
// Called when an element is no longer needed
@@ -418,7 +422,7 @@ public:
release();
}
- ListenerRecord* ref()
+ ListenerRecord *ref()
{
return mAlive ? mRef : 0;
}
@@ -473,7 +477,7 @@ public:
EventMapRecord *pCur = mHead;
while (pCur)
{
- EventMapRecord* aNext = pCur->mNext;
+ EventMapRecord *aNext = pCur->mNext;
if (pCur->ref() == aRec)
{
if (pCur == mHead)
@@ -495,13 +499,13 @@ public:
{
EventMapRecord *mCur;
- iterator()
- : mCur(0)
+ iterator() :
+ mCur(0)
{}
explicit
- iterator(EventMapRecord *aCur)
- : mCur(aCur)
+ iterator(EventMapRecord *aCur) :
+ mCur(aCur)
{
// Prevent element removal, till we're at it
if (mCur)
@@ -539,13 +543,13 @@ public:
}
bool
- operator==(const EventMapList::iterator& aOther) const
+ operator==(const EventMapList::iterator &aOther) const
{
return mCur == aOther.mCur;
}
bool
- operator!=(const EventMapList::iterator& aOther) const
+ operator!=(const EventMapList::iterator &aOther) const
{
return mCur != aOther.mCur;
}
@@ -563,7 +567,7 @@ public:
};
typedef EventMapList EventMap[NumEvents];
-typedef std::map<IEvent*, int32_t> PendingEventsMap;
+typedef std::map<IEvent *, int32_t> PendingEventsMap;
typedef std::deque<ComPtr<IEvent> > PassiveQueue;
class ListenerRecord
@@ -571,7 +575,7 @@ class ListenerRecord
private:
ComPtr<IEventListener> mListener;
BOOL mActive;
- EventSource* mOwner;
+ EventSource *mOwner;
RTSEMEVENT mQEvent;
RTCRITSECT mcsQLock;
@@ -580,24 +584,29 @@ private:
uint64_t mLastRead;
public:
- ListenerRecord(IEventListener* aListener,
- com::SafeArray<VBoxEventType_T>& aInterested,
- BOOL aActive,
- EventSource* aOwner);
+ ListenerRecord(IEventListener *aListener,
+ com::SafeArray<VBoxEventType_T> &aInterested,
+ BOOL aActive,
+ EventSource *aOwner);
~ListenerRecord();
- HRESULT process(IEvent* aEvent, BOOL aWaitable, PendingEventsMap::iterator& pit, AutoLockBase& alock);
- HRESULT enqueue(IEvent* aEvent);
- HRESULT dequeue(IEvent* *aEvent, LONG aTimeout, AutoLockBase& aAlock);
- HRESULT eventProcessed(IEvent * aEvent, PendingEventsMap::iterator& pit);
+ HRESULT process(IEvent *aEvent, BOOL aWaitable, PendingEventsMap::iterator &pit, AutoLockBase &alock);
+ HRESULT enqueue(IEvent *aEvent);
+ HRESULT dequeue(IEvent **aEvent, LONG aTimeout, AutoLockBase &aAlock);
+ HRESULT eventProcessed(IEvent *aEvent, PendingEventsMap::iterator &pit);
+ void shutdown();
+
void addRef()
{
ASMAtomicIncS32(&mRefCnt);
}
+
void release()
{
- if (ASMAtomicDecS32(&mRefCnt) <= 0) delete this;
+ if (ASMAtomicDecS32(&mRefCnt) <= 0)
+ delete this;
}
+
BOOL isActive()
{
return mActive;
@@ -611,15 +620,13 @@ template<typename Held>
class RecordHolder
{
public:
- RecordHolder(Held* lr)
- :
- held(lr)
+ RecordHolder(Held *lr) :
+ held(lr)
{
addref();
}
- RecordHolder(const RecordHolder& that)
- :
- held(that.held)
+ RecordHolder(const RecordHolder &that) :
+ held(that.held)
{
addref();
}
@@ -633,7 +640,7 @@ public:
release();
}
- Held* obj()
+ Held *obj()
{
return held;
}
@@ -644,7 +651,7 @@ public:
return *this;
}
private:
- Held* held;
+ Held *held;
void addref()
{
@@ -656,7 +663,7 @@ private:
if (held)
held->release();
}
- void safe_assign (Held *that_p)
+ void safe_assign(Held *that_p)
{
if (that_p)
that_p->addRef();
@@ -665,14 +672,17 @@ private:
}
};
-typedef std::map<IEventListener*, RecordHolder<ListenerRecord> > Listeners;
+typedef std::map<IEventListener *, RecordHolder<ListenerRecord> > Listeners;
struct EventSource::Data
{
- Data() {}
+ Data() : fShutdown(false)
+ {}
+
Listeners mListeners;
EventMap mEvMap;
PendingEventsMap mPendingMap;
+ bool fShutdown;
};
/**
@@ -685,24 +695,22 @@ static BOOL implies(VBoxEventType_T who, VBoxEventType_T what)
case VBoxEventType_Any:
return TRUE;
case VBoxEventType_Vetoable:
- return (what == VBoxEventType_OnExtraDataCanChange)
- || (what == VBoxEventType_OnCanShowWindow);
+ return (what == VBoxEventType_OnExtraDataCanChange)
+ || (what == VBoxEventType_OnCanShowWindow);
case VBoxEventType_MachineEvent:
- return (what == VBoxEventType_OnMachineStateChanged)
- || (what == VBoxEventType_OnMachineDataChanged)
- || (what == VBoxEventType_OnMachineRegistered)
- || (what == VBoxEventType_OnSessionStateChanged)
- || (what == VBoxEventType_OnGuestPropertyChanged);
+ return (what == VBoxEventType_OnMachineStateChanged)
+ || (what == VBoxEventType_OnMachineDataChanged)
+ || (what == VBoxEventType_OnMachineRegistered)
+ || (what == VBoxEventType_OnSessionStateChanged)
+ || (what == VBoxEventType_OnGuestPropertyChanged);
case VBoxEventType_SnapshotEvent:
- return (what == VBoxEventType_OnSnapshotTaken)
- || (what == VBoxEventType_OnSnapshotDeleted)
- || (what == VBoxEventType_OnSnapshotChanged)
- ;
+ return (what == VBoxEventType_OnSnapshotTaken)
+ || (what == VBoxEventType_OnSnapshotDeleted)
+ || (what == VBoxEventType_OnSnapshotChanged) ;
case VBoxEventType_InputEvent:
- return (what == VBoxEventType_OnKeyboardLedsChanged)
- || (what == VBoxEventType_OnMousePointerShapeChanged)
- || (what == VBoxEventType_OnMouseCapabilityChanged)
- ;
+ return (what == VBoxEventType_OnKeyboardLedsChanged)
+ || (what == VBoxEventType_OnMousePointerShapeChanged)
+ || (what == VBoxEventType_OnMouseCapabilityChanged);
case VBoxEventType_Invalid:
return FALSE;
default:
@@ -712,17 +720,14 @@ static BOOL implies(VBoxEventType_T who, VBoxEventType_T what)
return who == what;
}
-ListenerRecord::ListenerRecord(IEventListener* aListener,
- com::SafeArray<VBoxEventType_T>& aInterested,
- BOOL aActive,
- EventSource* aOwner)
- :
- mActive(aActive),
- mOwner(aOwner),
- mRefCnt(0)
+ListenerRecord::ListenerRecord(IEventListener *aListener,
+ com::SafeArray<VBoxEventType_T> &aInterested,
+ BOOL aActive,
+ EventSource *aOwner) :
+ mActive(aActive), mOwner(aOwner), mRefCnt(0)
{
mListener = aListener;
- EventMap* aEvMap = &aOwner->m->mEvMap;
+ EventMap *aEvMap = &aOwner->m->mEvMap;
for (size_t i = 0; i < aInterested.size(); ++i)
{
@@ -740,12 +745,12 @@ ListenerRecord::ListenerRecord(IEventListener* aListener,
if (!mActive)
{
::RTCritSectInit(&mcsQLock);
- ::RTSemEventCreate (&mQEvent);
+ ::RTSemEventCreate(&mQEvent);
mLastRead = RTTimeMilliTS();
}
else
{
- mQEvent =NIL_RTSEMEVENT;
+ mQEvent = NIL_RTSEMEVENT;
RT_ZERO(mcsQLock);
mLastRead = 0;
}
@@ -754,7 +759,7 @@ ListenerRecord::ListenerRecord(IEventListener* aListener,
ListenerRecord::~ListenerRecord()
{
/* Remove references to us from the event map */
- EventMap* aEvMap = &mOwner->m->mEvMap;
+ EventMap *aEvMap = &mOwner->m->mEvMap;
for (int j = FirstEvent; j < LastEvent; j++)
{
(*aEvMap)[j - FirstEvent].remove(this);
@@ -764,7 +769,7 @@ ListenerRecord::~ListenerRecord()
{
// at this moment nobody could add elements to our queue, so we can safely
// clean it up, otherwise there will be pending events map elements
- PendingEventsMap* aPem = &mOwner->m->mPendingMap;
+ PendingEventsMap *aPem = &mOwner->m->mPendingMap;
while (true)
{
ComPtr<IEvent> aEvent;
@@ -786,21 +791,21 @@ ListenerRecord::~ListenerRecord()
}
::RTCritSectDelete(&mcsQLock);
- ::RTSemEventDestroy(mQEvent);
}
+ shutdown();
}
-HRESULT ListenerRecord::process(IEvent* aEvent,
- BOOL aWaitable,
- PendingEventsMap::iterator& pit,
- AutoLockBase& aAlock)
+HRESULT ListenerRecord::process(IEvent *aEvent,
+ BOOL aWaitable,
+ PendingEventsMap::iterator &pit,
+ AutoLockBase &aAlock)
{
if (mActive)
{
/*
* We release lock here to allow modifying ops on EventSource inside callback.
*/
- HRESULT rc = S_OK;
+ HRESULT rc = S_OK;
if (mListener)
{
aAlock.release();
@@ -818,7 +823,7 @@ HRESULT ListenerRecord::process(IEvent* aEvent,
}
-HRESULT ListenerRecord::enqueue (IEvent* aEvent)
+HRESULT ListenerRecord::enqueue(IEvent *aEvent)
{
AssertMsg(!mActive, ("must be passive\n"));
@@ -829,7 +834,7 @@ HRESULT ListenerRecord::enqueue (IEvent* aEvent)
// and events keep coming, or queue is oversized we shall unregister this listener.
uint64_t sinceRead = RTTimeMilliTS() - mLastRead;
size_t queueSize = mQueue.size();
- if ( (queueSize > 1000) || ((queueSize > 500) && (sinceRead > 60 * 1000)))
+ if ((queueSize > 1000) || ((queueSize > 500) && (sinceRead > 60 * 1000)))
{
::RTCritSectLeave(&mcsQLock);
return E_ABORT;
@@ -845,15 +850,15 @@ HRESULT ListenerRecord::enqueue (IEvent* aEvent)
::RTCritSectLeave(&mcsQLock);
- // notify waiters
+ // notify waiters
::RTSemEventSignal(mQEvent);
return S_OK;
}
-HRESULT ListenerRecord::dequeue (IEvent* *aEvent,
- LONG aTimeout,
- AutoLockBase& aAlock)
+HRESULT ListenerRecord::dequeue(IEvent **aEvent,
+ LONG aTimeout,
+ AutoLockBase &aAlock)
{
if (mActive)
return VBOX_E_INVALID_OBJECT_STATE;
@@ -865,7 +870,8 @@ HRESULT ListenerRecord::dequeue (IEvent* *aEvent,
mLastRead = RTTimeMilliTS();
- if (mQueue.empty()) {
+ if (mQueue.empty())
+ {
::RTCritSectLeave(&mcsQLock);
// Speed up common case
if (aTimeout == 0)
@@ -893,7 +899,7 @@ HRESULT ListenerRecord::dequeue (IEvent* *aEvent,
return S_OK;
}
-HRESULT ListenerRecord::eventProcessed (IEvent* aEvent, PendingEventsMap::iterator& pit)
+HRESULT ListenerRecord::eventProcessed(IEvent *aEvent, PendingEventsMap::iterator &pit)
{
if (--pit->second == 0)
{
@@ -905,6 +911,16 @@ HRESULT ListenerRecord::eventProcessed (IEvent* aEvent, PendingEventsMap::iterat
return S_OK;
}
+void ListenerRecord::shutdown()
+{
+ if (mQEvent != NIL_RTSEMEVENT)
+ {
+ RTSEMEVENT tmp = mQEvent;
+ mQEvent = NIL_RTSEMEVENT;
+ ::RTSemEventDestroy(tmp);
+ }
+}
+
EventSource::EventSource()
{}
@@ -924,7 +940,7 @@ void EventSource::FinalRelease()
BaseFinalRelease();
}
-HRESULT EventSource::init(IUnknown *)
+HRESULT EventSource::init()
{
HRESULT rc = S_OK;
@@ -938,32 +954,58 @@ HRESULT EventSource::init(IUnknown *)
void EventSource::uninit()
{
+ {
+ // First of all (before even thinking about entering the uninit span):
+ // make sure that all listeners are are shut down (no pending events or
+ // wait calls), because they cannot be alive without the associated
+ // event source. Otherwise API clients which use long-term (or
+ // indefinite) waits will block VBoxSVC termination (just one example)
+ // for a long time or even infinitely long.
+ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (!m->fShutdown)
+ {
+ m->fShutdown = true;
+ for (Listeners::iterator it = m->mListeners.begin();
+ it != m->mListeners.end();
+ ++it)
+ {
+ it->second.obj()->shutdown();
+ }
+ }
+ }
+
AutoUninitSpan autoUninitSpan(this);
if (autoUninitSpan.uninitDone())
return;
+
m->mListeners.clear();
// m->mEvMap shall be cleared at this point too by destructors, assert?
}
-STDMETHODIMP EventSource::RegisterListener(IEventListener * aListener,
+STDMETHODIMP EventSource::RegisterListener(IEventListener *aListener,
ComSafeArrayIn(VBoxEventType_T, aInterested),
- BOOL aActive)
+ BOOL aActive)
{
CheckComArgNotNull(aListener);
CheckComArgSafeArrayNotNull(aInterested);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
{
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (m->fShutdown)
+ return setError(VBOX_E_INVALID_OBJECT_STATE,
+ tr("This event source is already shut down"));
+
Listeners::const_iterator it = m->mListeners.find(aListener);
if (it != m->mListeners.end())
return setError(E_INVALIDARG,
tr("This listener already registered"));
- com::SafeArray<VBoxEventType_T> interested(ComSafeArrayInArg (aInterested));
+ com::SafeArray<VBoxEventType_T> interested(ComSafeArrayInArg(aInterested));
RecordHolder<ListenerRecord> lrh(new ListenerRecord(aListener, interested, aActive, this));
m->mListeners.insert(Listeners::value_type(aListener, lrh));
}
@@ -975,12 +1017,13 @@ STDMETHODIMP EventSource::RegisterListener(IEventListener * aListener,
return S_OK;
}
-STDMETHODIMP EventSource::UnregisterListener(IEventListener * aListener)
+STDMETHODIMP EventSource::UnregisterListener(IEventListener *aListener)
{
CheckComArgNotNull(aListener);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT rc;
{
@@ -990,6 +1033,7 @@ STDMETHODIMP EventSource::UnregisterListener(IEventListener * aListener)
if (it != m->mListeners.end())
{
+ it->second.obj()->shutdown();
m->mListeners.erase(it);
// destructor removes refs from the event map
rc = S_OK;
@@ -1011,15 +1055,16 @@ STDMETHODIMP EventSource::UnregisterListener(IEventListener * aListener)
return rc;
}
-STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
- LONG aTimeout,
- BOOL *aProcessed)
+STDMETHODIMP EventSource::FireEvent(IEvent *aEvent,
+ LONG aTimeout,
+ BOOL *aProcessed)
{
CheckComArgNotNull(aEvent);
CheckComArgOutPointerValid(aProcessed);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT hrc;
BOOL aWaitable = FALSE;
@@ -1028,6 +1073,10 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
do {
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (m->fShutdown)
+ return setError(VBOX_E_INVALID_OBJECT_STATE,
+ tr("This event source is already shut down"));
+
VBoxEventType_T evType;
hrc = aEvent->COMGETTER(Type)(&evType);
AssertComRCReturn(hrc, hrc);
@@ -1074,7 +1123,10 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
{
Listeners::iterator lit = m->mListeners.find(record.obj()->mListener);
if (lit != m->mListeners.end())
+ {
+ lit->second.obj()->shutdown();
m->mListeners.erase(lit);
+ }
}
// anything else to do with cbRc?
}
@@ -1090,18 +1142,23 @@ STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
}
-STDMETHODIMP EventSource::GetEvent(IEventListener * aListener,
- LONG aTimeout,
- IEvent ** aEvent)
+STDMETHODIMP EventSource::GetEvent(IEventListener *aListener,
+ LONG aTimeout,
+ IEvent **aEvent)
{
CheckComArgNotNull(aListener);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (m->fShutdown)
+ return setError(VBOX_E_INVALID_OBJECT_STATE,
+ tr("This event source is already shut down"));
+
Listeners::iterator it = m->mListeners.find(aListener);
HRESULT rc;
@@ -1117,17 +1174,22 @@ STDMETHODIMP EventSource::GetEvent(IEventListener * aListener,
return rc;
}
-STDMETHODIMP EventSource::EventProcessed(IEventListener * aListener,
- IEvent * aEvent)
+STDMETHODIMP EventSource::EventProcessed(IEventListener *aListener,
+ IEvent *aEvent)
{
CheckComArgNotNull(aListener);
CheckComArgNotNull(aEvent);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+ if (m->fShutdown)
+ return setError(VBOX_E_INVALID_OBJECT_STATE,
+ tr("This event source is already shut down"));
+
Listeners::iterator it = m->mListeners.find(aListener);
HRESULT rc;
@@ -1136,11 +1198,11 @@ STDMETHODIMP EventSource::EventProcessed(IEventListener * aListener,
if (it != m->mListeners.end())
{
- ListenerRecord* aRecord = it->second.obj();
+ ListenerRecord *aRecord = it->second.obj();
if (aRecord->isActive())
return setError(E_INVALIDARG,
- tr("Only applicable to passive listeners"));
+ tr("Only applicable to passive listeners"));
if (aWaitable)
{
@@ -1246,14 +1308,14 @@ public:
BaseFinalRelease();
}
- HRESULT init(IEventSource* aSource)
+ HRESULT init(IEventSource *aSource)
{
mSource = aSource;
return S_OK;
}
// IEventListener methods
- STDMETHOD(HandleEvent)(IEvent * aEvent)
+ STDMETHOD(HandleEvent)(IEvent *aEvent)
{
BOOL fProcessed = FALSE;
if (mSource)
@@ -1269,7 +1331,7 @@ class ATL_NO_VTABLE EventSourceAggregator :
{
typedef std::list <ComPtr<IEventSource> > EventSourceList;
/* key is weak reference */
- typedef std::map<IEventListener*, ComPtr<IEventListener> > ProxyListenerMap;
+ typedef std::map<IEventListener *, ComPtr<IEventListener> > ProxyListenerMap;
EventSourceList mEventSources;
ProxyListenerMap mListenerProxies;
@@ -1308,28 +1370,28 @@ public:
HRESULT init(ComSafeArrayIn(IEventSource *, aSources));
// IEventSource methods
- STDMETHOD(CreateListener)(IEventListener ** aListener);
- STDMETHOD(CreateAggregator)(ComSafeArrayIn(IEventSource*, aSubordinates),
- IEventSource ** aAggregator);
- STDMETHOD(RegisterListener)(IEventListener * aListener,
+ STDMETHOD(CreateListener)(IEventListener **aListener);
+ STDMETHOD(CreateAggregator)(ComSafeArrayIn(IEventSource *, aSubordinates),
+ IEventSource **aAggregator);
+ STDMETHOD(RegisterListener)(IEventListener *aListener,
ComSafeArrayIn(VBoxEventType_T, aInterested),
- BOOL aActive);
- STDMETHOD(UnregisterListener)(IEventListener * aListener);
- STDMETHOD(FireEvent)(IEvent * aEvent,
- LONG aTimeout,
- BOOL *aProcessed);
- STDMETHOD(GetEvent)(IEventListener * aListener,
- LONG aTimeout,
- IEvent * *aEvent);
- STDMETHOD(EventProcessed)(IEventListener * aListener,
- IEvent * aEvent);
+ BOOL aActive);
+ STDMETHOD(UnregisterListener)(IEventListener *aListener);
+ STDMETHOD(FireEvent)(IEvent *aEvent,
+ LONG aTimeout,
+ BOOL *aProcessed);
+ STDMETHOD(GetEvent)(IEventListener *aListener,
+ LONG aTimeout,
+ IEvent **aEvent);
+ STDMETHOD(EventProcessed)(IEventListener *aListener,
+ IEvent *aEvent);
protected:
- HRESULT createProxyListener(IEventListener * aListener,
- IEventListener * *aProxy);
- HRESULT getProxyListener (IEventListener * aListener,
- IEventListener * *aProxy);
- HRESULT removeProxyListener(IEventListener * aListener);
+ HRESULT createProxyListener(IEventListener *aListener,
+ IEventListener **aProxy);
+ HRESULT getProxyListener(IEventListener *aListener,
+ IEventListener **aProxy);
+ HRESULT removeProxyListener(IEventListener *aListener);
};
#ifdef VBOX_WITH_XPCOM
@@ -1348,12 +1410,13 @@ NS_IMPL_THREADSAFE_ISUPPORTS1_CI(EventSourceAggregator, IEventSource)
#endif
-STDMETHODIMP EventSource::CreateListener(IEventListener ** aListener)
+STDMETHODIMP EventSource::CreateListener(IEventListener **aListener)
{
CheckComArgOutPointerValid(aListener);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
ComObjPtr<PassiveEventListener> listener;
@@ -1365,13 +1428,14 @@ STDMETHODIMP EventSource::CreateListener(IEventListener ** aListener)
}
-STDMETHODIMP EventSource::CreateAggregator(ComSafeArrayIn(IEventSource*, aSubordinates),
- IEventSource ** aResult)
+STDMETHODIMP EventSource::CreateAggregator(ComSafeArrayIn(IEventSource *, aSubordinates),
+ IEventSource **aResult)
{
CheckComArgOutPointerValid(aResult);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
ComObjPtr<EventSourceAggregator> agg;
@@ -1383,12 +1447,11 @@ STDMETHODIMP EventSource::CreateAggregator(ComSafeArrayIn(IEventSource*, aSubord
if (FAILED(rc))
return rc;
-
agg.queryInterfaceTo(aResult);
return S_OK;
}
-HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource*, aSourcesIn))
+HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource *, aSourcesIn))
{
HRESULT rc;
@@ -1398,7 +1461,7 @@ HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource*, aSourcesIn))
rc = mSource.createObject();
ComAssertMsgRet(SUCCEEDED(rc), ("Could not create source (%Rhrc)", rc),
E_FAIL);
- rc = mSource->init((IEventSource*)this);
+ rc = mSource->init();
ComAssertMsgRet(SUCCEEDED(rc), ("Could not init source (%Rhrc)", rc),
E_FAIL);
@@ -1418,26 +1481,27 @@ HRESULT EventSourceAggregator::init(ComSafeArrayIn(IEventSource*, aSourcesIn))
return rc;
}
-STDMETHODIMP EventSourceAggregator::CreateListener(IEventListener ** aListener)
+STDMETHODIMP EventSourceAggregator::CreateListener(IEventListener **aListener)
{
return mSource->CreateListener(aListener);
}
-STDMETHODIMP EventSourceAggregator::CreateAggregator(ComSafeArrayIn(IEventSource*, aSubordinates),
- IEventSource ** aResult)
+STDMETHODIMP EventSourceAggregator::CreateAggregator(ComSafeArrayIn(IEventSource *, aSubordinates),
+ IEventSource **aResult)
{
return mSource->CreateAggregator(ComSafeArrayInArg(aSubordinates), aResult);
}
-STDMETHODIMP EventSourceAggregator::RegisterListener(IEventListener * aListener,
+STDMETHODIMP EventSourceAggregator::RegisterListener(IEventListener *aListener,
ComSafeArrayIn(VBoxEventType_T, aInterested),
- BOOL aActive)
+ BOOL aActive)
{
CheckComArgNotNull(aListener);
CheckComArgSafeArrayNotNull(aInterested);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT rc;
@@ -1462,12 +1526,13 @@ STDMETHODIMP EventSourceAggregator::RegisterListener(IEventListener * aListener,
return rc;
}
-STDMETHODIMP EventSourceAggregator::UnregisterListener(IEventListener * aListener)
+STDMETHODIMP EventSourceAggregator::UnregisterListener(IEventListener *aListener)
{
CheckComArgNotNull(aListener);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT rc = S_OK;
@@ -1490,19 +1555,20 @@ STDMETHODIMP EventSourceAggregator::UnregisterListener(IEventListener * aListene
}
-STDMETHODIMP EventSourceAggregator::FireEvent(IEvent * aEvent,
- LONG aTimeout,
- BOOL *aProcessed)
+STDMETHODIMP EventSourceAggregator::FireEvent(IEvent *aEvent,
+ LONG aTimeout,
+ BOOL *aProcessed)
{
CheckComArgNotNull(aEvent);
CheckComArgOutPointerValid(aProcessed);
AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
+ if (FAILED(autoCaller.rc()))
+ return autoCaller.rc();
HRESULT rc = S_OK;
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
- /* Aggresgator event source shalln't have direct event firing, but we may
+ /* Aggregator event source shall not have direct event firing, but we may
wish to support aggregation chains */
for (EventSourceList::const_iterator it = mEventSources.begin(); it != mEventSources.end();
++it)
@@ -1517,21 +1583,21 @@ STDMETHODIMP EventSourceAggregator::FireEvent(IEvent * aEvent,
return S_OK;
}
-STDMETHODIMP EventSourceAggregator::GetEvent(IEventListener * aListener,
- LONG aTimeout,
- IEvent ** aEvent)
+STDMETHODIMP EventSourceAggregator::GetEvent(IEventListener *aListener,
+ LONG aTimeout,
+ IEvent **aEvent)
{
return mSource->GetEvent(aListener, aTimeout, aEvent);
}
-STDMETHODIMP EventSourceAggregator::EventProcessed(IEventListener * aListener,
- IEvent * aEvent)
+STDMETHODIMP EventSourceAggregator::EventProcessed(IEventListener *aListener,
+ IEvent *aEvent)
{
return mSource->EventProcessed(aListener, aEvent);
}
-HRESULT EventSourceAggregator::createProxyListener(IEventListener * aListener,
- IEventListener * *aProxy)
+HRESULT EventSourceAggregator::createProxyListener(IEventListener *aListener,
+ IEventListener **aProxy)
{
ComObjPtr<ProxyEventListener> proxy;
@@ -1554,8 +1620,8 @@ HRESULT EventSourceAggregator::createProxyListener(IEventListener * aListener,
return S_OK;
}
-HRESULT EventSourceAggregator::getProxyListener(IEventListener * aListener,
- IEventListener * *aProxy)
+HRESULT EventSourceAggregator::getProxyListener(IEventListener *aListener,
+ IEventListener **aProxy)
{
ProxyListenerMap::const_iterator it = mListenerProxies.find(aListener);
if (it == mListenerProxies.end())
@@ -1566,7 +1632,7 @@ HRESULT EventSourceAggregator::getProxyListener(IEventListener * aListener,
return S_OK;
}
-HRESULT EventSourceAggregator::removeProxyListener(IEventListener * aListener)
+HRESULT EventSourceAggregator::removeProxyListener(IEventListener *aListener)
{
ProxyListenerMap::iterator it = mListenerProxies.find(aListener);
if (it == mListenerProxies.end())
diff --git a/src/VBox/Main/src-client/ConsoleImpl.cpp b/src/VBox/Main/src-client/ConsoleImpl.cpp
index 78d97f7eb..d0c74c245 100644
--- a/src/VBox/Main/src-client/ConsoleImpl.cpp
+++ b/src/VBox/Main/src-client/ConsoleImpl.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2005-2013 Oracle Corporation
+ * Copyright (C) 2005-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -489,7 +489,7 @@ HRESULT Console::init(IMachine *aMachine, IInternalMachineControl *aControl, Loc
// Event source may be needed by other children
unconst(mEventSource).createObject();
- rc = mEventSource->init(static_cast<IConsole*>(this));
+ rc = mEventSource->init();
AssertComRCReturnRC(rc);
mcAudioRefs = 0;
@@ -2394,7 +2394,7 @@ HRESULT Console::doCPURemove(ULONG aCpu, PUVM pUVM)
*/
PVMREQ pReq;
vrc = VMR3ReqCallU(pUVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
- (PFNRT)Console::unplugCpu, 3,
+ (PFNRT)unplugCpu, 3,
this, pUVM, (VMCPUID)aCpu);
if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
{
@@ -2500,7 +2500,7 @@ HRESULT Console::doCPUAdd(ULONG aCpu, PUVM pUVM)
*/
PVMREQ pReq;
int vrc = VMR3ReqCallU(pUVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
- (PFNRT)Console::plugCpu, 3,
+ (PFNRT)plugCpu, 3,
this, pUVM, aCpu);
/* release the lock before a VMR3* call (EMT will call us back)! */
@@ -3505,6 +3505,83 @@ HRESULT Console::convertBusPortDeviceToLun(StorageBus_T enmBus, LONG port, LONG
// private methods
/////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Suspend the VM before we do any medium or network attachment change.
+ *
+ * @param pUVM Safe VM handle.
+ * @param pAlock The automatic lock instance. This is for when we have
+ * to leave it in order to avoid deadlocks.
+ * @param pfSuspend where to store the information if we need to resume
+ * afterwards.
+ */
+HRESULT Console::suspendBeforeConfigChange(PUVM pUVM, AutoWriteLock *pAlock, bool *pfResume)
+{
+ *pfResume = false;
+ VMSTATE enmVMState = VMR3GetStateU(pUVM);
+ switch (enmVMState)
+ {
+ case VMSTATE_RESETTING:
+ case VMSTATE_RUNNING:
+ {
+ LogFlowFunc(("Suspending the VM...\n"));
+ /* disable the callback to prevent Console-level state change */
+ mVMStateChangeCallbackDisabled = true;
+ if (pAlock)
+ pAlock->release();
+ int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
+ if (pAlock)
+ pAlock->acquire();
+ mVMStateChangeCallbackDisabled = false;
+ if (RT_FAILURE(rc))
+ return setErrorInternal(VBOX_E_INVALID_VM_STATE,
+ COM_IIDOF(IConsole),
+ getStaticComponentName(),
+ Utf8StrFmt("Couldn't suspend VM for medium change (%Rrc)", rc),
+ false /*aWarning*/,
+ true /*aLogIt*/);
+ *pfResume = true;
+ break;
+ }
+ case VMSTATE_SUSPENDED:
+ break;
+ default:
+ return setErrorInternal(VBOX_E_INVALID_VM_STATE,
+ COM_IIDOF(IConsole),
+ getStaticComponentName(),
+ Utf8StrFmt("Invalid VM state '%s' for changing medium",
+ VMR3GetStateName(enmVMState)),
+ false /*aWarning*/,
+ true /*aLogIt*/);
+ }
+
+ return S_OK;
+}
+
+/**
+ * Resume the VM after we did any medium or network attachment change.
+ * This is the counterpart to Console::suspendBeforeConfigChange().
+ *
+ * @param pUVM Safe VM handle.
+ */
+void Console::resumeAfterConfigChange(PUVM pUVM)
+{
+ LogFlowFunc(("Resuming the VM...\n"));
+ /* disable the callback to prevent Console-level state change */
+ mVMStateChangeCallbackDisabled = true;
+ int rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
+ mVMStateChangeCallbackDisabled = false;
+ AssertRC(rc);
+ if (RT_FAILURE(rc))
+ {
+ VMSTATE enmVMState = VMR3GetStateU(pUVM);
+ if (enmVMState == VMSTATE_SUSPENDED)
+ {
+ /* too bad, we failed. try to sync the console state with the VMM state */
+ vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, this);
+ }
+ }
+}
/**
* Process a medium change.
@@ -3574,26 +3651,23 @@ HRESULT Console::doMediumChange(IMediumAttachment *aMediumAttachment, bool fForc
AssertComRC(rc);
/*
+ * Suspend the VM first. The VM must not be running since it might have
+ * pending I/O to the drive which is being changed.
+ */
+ bool fResume = false;
+ rc = suspendBeforeConfigChange(pUVM, &alock, &fResume);
+ if (FAILED(rc))
+ return rc;
+
+ /*
* Call worker in EMT, that's faster and safer than doing everything
* using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait
* here to make requests from under the lock in order to serialize them.
*/
PVMREQ pReq;
- int vrc = VMR3ReqCallU(pUVM,
- VMCPUID_ANY,
- &pReq,
- 0 /* no wait! */,
- VMREQFLAGS_VBOX_STATUS,
- (PFNRT)Console::changeRemovableMedium,
- 8,
- this,
- pUVM,
- pszDevice,
- uInstance,
- enmBus,
- fUseHostIOCache,
- aMediumAttachment,
- fForce);
+ int vrc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+ (PFNRT)changeRemovableMedium, 8,
+ this, pUVM, pszDevice, uInstance, enmBus, fUseHostIOCache, aMediumAttachment, fForce);
/* release the lock before waiting for a result (EMT will call us back!) */
alock.release();
@@ -3607,6 +3681,9 @@ HRESULT Console::doMediumChange(IMediumAttachment *aMediumAttachment, bool fForc
}
VMR3ReqFree(pReq);
+ if (fResume)
+ resumeAfterConfigChange(pUVM);
+
if (RT_SUCCESS(vrc))
{
LogFlowThisFunc(("Returns S_OK\n"));
@@ -3642,8 +3719,9 @@ HRESULT Console::doMediumChange(IMediumAttachment *aMediumAttachment, bool fForc
* @param fPassthrough Enables using passthrough mode of the host DVD drive if applicable.
*
* @thread EMT
+ * @note The VM must not be running since it might have pending I/O to the drive which is being changed.
*/
-DECLCALLBACK(int) Console::changeRemovableMedium(Console *pConsole,
+DECLCALLBACK(int) Console::changeRemovableMedium(Console *pThis,
PUVM pUVM,
const char *pcszDevice,
unsigned uInstance,
@@ -3652,112 +3730,49 @@ DECLCALLBACK(int) Console::changeRemovableMedium(Console *pConsole,
IMediumAttachment *aMediumAtt,
bool fForce)
{
- LogFlowFunc(("pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p, fForce=%d\n",
- pConsole, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt, fForce));
+ LogFlowFunc(("pThis=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p, fForce=%d\n",
+ pThis, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt, fForce));
- AssertReturn(pConsole, VERR_INVALID_PARAMETER);
+ AssertReturn(pThis, VERR_INVALID_PARAMETER);
- AutoCaller autoCaller(pConsole);
+ AutoCaller autoCaller(pThis);
AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
/*
- * Suspend the VM first.
- *
- * The VM must not be running since it might have pending I/O to
- * the drive which is being changed.
+ * Check the VM for correct state.
*/
- bool fResume;
VMSTATE enmVMState = VMR3GetStateU(pUVM);
- switch (enmVMState)
- {
- case VMSTATE_RESETTING:
- case VMSTATE_RUNNING:
- {
- LogFlowFunc(("Suspending the VM...\n"));
- /* disable the callback to prevent Console-level state change */
- pConsole->mVMStateChangeCallbackDisabled = true;
- int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
- pConsole->mVMStateChangeCallbackDisabled = false;
- AssertRCReturn(rc, rc);
- fResume = true;
- break;
- }
-
- case VMSTATE_SUSPENDED:
- case VMSTATE_CREATED:
- case VMSTATE_OFF:
- fResume = false;
- break;
-
- case VMSTATE_RUNNING_LS:
- case VMSTATE_RUNNING_FT:
- return setErrorInternal(VBOX_E_INVALID_VM_STATE,
- COM_IIDOF(IConsole),
- getStaticComponentName(),
- (enmVMState == VMSTATE_RUNNING_LS) ? Utf8Str(tr("Cannot change drive during live migration")) : Utf8Str(tr("Cannot change drive during fault tolerant syncing")),
- false /*aWarning*/,
- true /*aLogIt*/);
-
- default:
- AssertMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED);
- }
+ AssertReturn(enmVMState == VMSTATE_SUSPENDED, VERR_INVALID_STATE);
/* Determine the base path for the device instance. */
PCFGMNODE pCtlInst;
pCtlInst = CFGMR3GetChildF(CFGMR3GetRootU(pUVM), "Devices/%s/%u/", pcszDevice, uInstance);
AssertReturn(pCtlInst, VERR_INTERNAL_ERROR);
- int rc = VINF_SUCCESS;
- int rcRet = VINF_SUCCESS;
-
- rcRet = pConsole->configMediumAttachment(pCtlInst,
- pcszDevice,
- uInstance,
- enmBus,
- fUseHostIOCache,
- false /* fSetupMerge */,
- false /* fBuiltinIOCache */,
- 0 /* uMergeSource */,
- 0 /* uMergeTarget */,
- aMediumAtt,
- pConsole->mMachineState,
- NULL /* phrc */,
- true /* fAttachDetach */,
- fForce /* fForceUnmount */,
- false /* fHotplug */,
- pUVM,
- NULL /* paLedDevType */);
- /** @todo this dumps everything attached to this device instance, which
- * is more than necessary. Dumping the changed LUN would be enough. */
- CFGMR3Dump(pCtlInst);
-
- /*
- * Resume the VM if necessary.
- */
- if (fResume)
- {
- LogFlowFunc(("Resuming the VM...\n"));
- /* disable the callback to prevent Console-level state change */
- pConsole->mVMStateChangeCallbackDisabled = true;
- rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
- pConsole->mVMStateChangeCallbackDisabled = false;
- AssertRC(rc);
- if (RT_FAILURE(rc))
- {
- /* too bad, we failed. try to sync the console state with the VMM state */
- vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, pConsole);
- }
- /// @todo (r=dmik) if we failed with drive mount, then the VMR3Resume
- // error (if any) will be hidden from the caller. For proper reporting
- // of such multiple errors to the caller we need to enhance the
- // IVirtualBoxError interface. For now, give the first error the higher
- // priority.
- if (RT_SUCCESS(rcRet))
- rcRet = rc;
- }
-
- LogFlowFunc(("Returning %Rrc\n", rcRet));
- return rcRet;
+ PCFGMNODE pLunL0 = NULL;
+ int rc = pThis->configMediumAttachment(pCtlInst,
+ pcszDevice,
+ uInstance,
+ enmBus,
+ fUseHostIOCache,
+ false /* fSetupMerge */,
+ false /* fBuiltinIOCache */,
+ 0 /* uMergeSource */,
+ 0 /* uMergeTarget */,
+ aMediumAtt,
+ pThis->mMachineState,
+ NULL /* phrc */,
+ true /* fAttachDetach */,
+ fForce /* fForceUnmount */,
+ false /* fHotplug */,
+ pUVM,
+ NULL /* paLedDevType */,
+ &pLunL0);
+ /* Dump the changed LUN if possible, dump the complete device otherwise */
+ CFGMR3Dump(pLunL0 ? pLunL0 : pCtlInst);
+
+ LogFlowFunc(("Returning %Rrc\n", rc));
+ return rc;
}
@@ -3829,26 +3844,23 @@ HRESULT Console::doStorageDeviceAttach(IMediumAttachment *aMediumAttachment, PUV
AssertComRC(rc);
/*
+ * Suspend the VM first. The VM must not be running since it might have
+ * pending I/O to the drive which is being changed.
+ */
+ bool fResume = false;
+ rc = suspendBeforeConfigChange(pUVM, &alock, &fResume);
+ if (FAILED(rc))
+ return rc;
+
+ /*
* Call worker in EMT, that's faster and safer than doing everything
* using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait
* here to make requests from under the lock in order to serialize them.
*/
PVMREQ pReq;
- int vrc = VMR3ReqCallU(pUVM,
- VMCPUID_ANY,
- &pReq,
- 0 /* no wait! */,
- VMREQFLAGS_VBOX_STATUS,
- (PFNRT)Console::attachStorageDevice,
- 8,
- this,
- pUVM,
- pszDevice,
- uInstance,
- enmBus,
- fUseHostIOCache,
- aMediumAttachment,
- fSilent);
+ int vrc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+ (PFNRT)attachStorageDevice, 8,
+ this, pUVM, pszDevice, uInstance, enmBus, fUseHostIOCache, aMediumAttachment, fSilent);
/* release the lock before waiting for a result (EMT will call us back!) */
alock.release();
@@ -3862,6 +3874,9 @@ HRESULT Console::doStorageDeviceAttach(IMediumAttachment *aMediumAttachment, PUV
}
VMR3ReqFree(pReq);
+ if (fResume)
+ resumeAfterConfigChange(pUVM);
+
if (RT_SUCCESS(vrc))
{
LogFlowThisFunc(("Returns S_OK\n"));
@@ -3891,8 +3906,9 @@ HRESULT Console::doStorageDeviceAttach(IMediumAttachment *aMediumAttachment, PUV
* @param fSilent Flag whether to inform the guest about the attached device.
*
* @thread EMT
+ * @note The VM must not be running since it might have pending I/O to the drive which is being changed.
*/
-DECLCALLBACK(int) Console::attachStorageDevice(Console *pConsole,
+DECLCALLBACK(int) Console::attachStorageDevice(Console *pThis,
PUVM pUVM,
const char *pcszDevice,
unsigned uInstance,
@@ -3901,113 +3917,49 @@ DECLCALLBACK(int) Console::attachStorageDevice(Console *pConsole,
IMediumAttachment *aMediumAtt,
bool fSilent)
{
- LogFlowFunc(("pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p\n",
- pConsole, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt));
+ LogFlowFunc(("pThis=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, aMediumAtt=%p\n",
+ pThis, uInstance, pcszDevice, pcszDevice, enmBus, aMediumAtt));
- AssertReturn(pConsole, VERR_INVALID_PARAMETER);
+ AssertReturn(pThis, VERR_INVALID_PARAMETER);
- AutoCaller autoCaller(pConsole);
+ AutoCaller autoCaller(pThis);
AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
/*
- * Suspend the VM first.
- *
- * The VM must not be running since it might have pending I/O to
- * the drive which is being changed.
+ * Check the VM for correct state.
*/
- bool fResume;
VMSTATE enmVMState = VMR3GetStateU(pUVM);
- switch (enmVMState)
- {
- case VMSTATE_RESETTING:
- case VMSTATE_RUNNING:
- {
- LogFlowFunc(("Suspending the VM...\n"));
- /* disable the callback to prevent Console-level state change */
- pConsole->mVMStateChangeCallbackDisabled = true;
- int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
- pConsole->mVMStateChangeCallbackDisabled = false;
- AssertRCReturn(rc, rc);
- fResume = true;
- break;
- }
-
- case VMSTATE_SUSPENDED:
- case VMSTATE_CREATED:
- case VMSTATE_OFF:
- fResume = false;
- break;
-
- case VMSTATE_RUNNING_LS:
- case VMSTATE_RUNNING_FT:
- return setErrorInternal(VBOX_E_INVALID_VM_STATE,
- COM_IIDOF(IConsole),
- getStaticComponentName(),
- (enmVMState == VMSTATE_RUNNING_LS) ? Utf8Str(tr("Cannot change drive during live migration")) : Utf8Str(tr("Cannot change drive during fault tolerant syncing")),
- false /*aWarning*/,
- true /*aLogIt*/);
-
- default:
- AssertMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED);
- }
+ AssertReturn(enmVMState == VMSTATE_SUSPENDED, VERR_INVALID_STATE);
/* Determine the base path for the device instance. */
PCFGMNODE pCtlInst;
pCtlInst = CFGMR3GetChildF(CFGMR3GetRootU(pUVM), "Devices/%s/%u/", pcszDevice, uInstance);
AssertReturn(pCtlInst, VERR_INTERNAL_ERROR);
- int rc = VINF_SUCCESS;
- int rcRet = VINF_SUCCESS;
-
- rcRet = pConsole->configMediumAttachment(pCtlInst,
- pcszDevice,
- uInstance,
- enmBus,
- fUseHostIOCache,
- false /* fSetupMerge */,
- false /* fBuiltinIOCache */,
- 0 /* uMergeSource */,
- 0 /* uMergeTarget */,
- aMediumAtt,
- pConsole->mMachineState,
- NULL /* phrc */,
- true /* fAttachDetach */,
- false /* fForceUnmount */,
- !fSilent /* fHotplug */,
- pUVM,
- NULL /* paLedDevType */);
- /** @todo this dumps everything attached to this device instance, which
- * is more than necessary. Dumping the changed LUN would be enough. */
- CFGMR3Dump(pCtlInst);
-
- /*
- * Resume the VM if necessary.
- */
- if (fResume)
- {
- LogFlowFunc(("Resuming the VM...\n"));
- /* disable the callback to prevent Console-level state change */
- pConsole->mVMStateChangeCallbackDisabled = true;
- rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
- pConsole->mVMStateChangeCallbackDisabled = false;
- AssertRC(rc);
- if (RT_FAILURE(rc))
- {
- /* too bad, we failed. try to sync the console state with the VMM state */
- vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, pConsole);
- }
- /** @todo if we failed with drive mount, then the VMR3Resume
- * error (if any) will be hidden from the caller. For proper reporting
- * of such multiple errors to the caller we need to enhance the
- * IVirtualBoxError interface. For now, give the first error the higher
- * priority.
- */
- if (RT_SUCCESS(rcRet))
- rcRet = rc;
- }
-
- LogFlowFunc(("Returning %Rrc\n", rcRet));
- return rcRet;
+ PCFGMNODE pLunL0 = NULL;
+ int rc = pThis->configMediumAttachment(pCtlInst,
+ pcszDevice,
+ uInstance,
+ enmBus,
+ fUseHostIOCache,
+ false /* fSetupMerge */,
+ false /* fBuiltinIOCache */,
+ 0 /* uMergeSource */,
+ 0 /* uMergeTarget */,
+ aMediumAtt,
+ pThis->mMachineState,
+ NULL /* phrc */,
+ true /* fAttachDetach */,
+ false /* fForceUnmount */,
+ !fSilent /* fHotplug */,
+ pUVM,
+ NULL /* paLedDevType */,
+ &pLunL0);
+ /* Dump the changed LUN if possible, dump the complete device otherwise */
+ CFGMR3Dump(pLunL0 ? pLunL0 : pCtlInst);
+
+ LogFlowFunc(("Returning %Rrc\n", rc));
+ return rc;
}
/**
@@ -4075,25 +4027,23 @@ HRESULT Console::doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PUV
AssertComRC(rc);
/*
+ * Suspend the VM first. The VM must not be running since it might have
+ * pending I/O to the drive which is being changed.
+ */
+ bool fResume = false;
+ rc = suspendBeforeConfigChange(pUVM, &alock, &fResume);
+ if (FAILED(rc))
+ return rc;
+
+ /*
* Call worker in EMT, that's faster and safer than doing everything
* using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait
* here to make requests from under the lock in order to serialize them.
*/
PVMREQ pReq;
- int vrc = VMR3ReqCallU(pUVM,
- VMCPUID_ANY,
- &pReq,
- 0 /* no wait! */,
- VMREQFLAGS_VBOX_STATUS,
- (PFNRT)Console::detachStorageDevice,
- 7,
- this,
- pUVM,
- pszDevice,
- uInstance,
- enmBus,
- aMediumAttachment,
- fSilent);
+ int vrc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+ (PFNRT)detachStorageDevice, 7,
+ this, pUVM, pszDevice, uInstance, enmBus, aMediumAttachment, fSilent);
/* release the lock before waiting for a result (EMT will call us back!) */
alock.release();
@@ -4107,6 +4057,9 @@ HRESULT Console::doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PUV
}
VMR3ReqFree(pReq);
+ if (fResume)
+ resumeAfterConfigChange(pUVM);
+
if (RT_SUCCESS(vrc))
{
LogFlowThisFunc(("Returns S_OK\n"));
@@ -4135,8 +4088,9 @@ HRESULT Console::doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PUV
* @param fSilent Flag whether to notify the guest about the detached device.
*
* @thread EMT
+ * @note The VM must not be running since it might have pending I/O to the drive which is being changed.
*/
-DECLCALLBACK(int) Console::detachStorageDevice(Console *pConsole,
+DECLCALLBACK(int) Console::detachStorageDevice(Console *pThis,
PUVM pUVM,
const char *pcszDevice,
unsigned uInstance,
@@ -4144,55 +4098,19 @@ DECLCALLBACK(int) Console::detachStorageDevice(Console *pConsole,
IMediumAttachment *pMediumAtt,
bool fSilent)
{
- LogFlowFunc(("pConsole=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, pMediumAtt=%p\n",
- pConsole, uInstance, pcszDevice, pcszDevice, enmBus, pMediumAtt));
+ LogFlowFunc(("pThis=%p uInstance=%u pszDevice=%p:{%s} enmBus=%u, pMediumAtt=%p\n",
+ pThis, uInstance, pcszDevice, pcszDevice, enmBus, pMediumAtt));
- AssertReturn(pConsole, VERR_INVALID_PARAMETER);
+ AssertReturn(pThis, VERR_INVALID_PARAMETER);
- AutoCaller autoCaller(pConsole);
+ AutoCaller autoCaller(pThis);
AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
/*
- * Suspend the VM first.
- *
- * The VM must not be running since it might have pending I/O to
- * the drive which is being changed.
+ * Check the VM for correct state.
*/
- bool fResume;
VMSTATE enmVMState = VMR3GetStateU(pUVM);
- switch (enmVMState)
- {
- case VMSTATE_RESETTING:
- case VMSTATE_RUNNING:
- {
- LogFlowFunc(("Suspending the VM...\n"));
- /* disable the callback to prevent Console-level state change */
- pConsole->mVMStateChangeCallbackDisabled = true;
- int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
- pConsole->mVMStateChangeCallbackDisabled = false;
- AssertRCReturn(rc, rc);
- fResume = true;
- break;
- }
-
- case VMSTATE_SUSPENDED:
- case VMSTATE_CREATED:
- case VMSTATE_OFF:
- fResume = false;
- break;
-
- case VMSTATE_RUNNING_LS:
- case VMSTATE_RUNNING_FT:
- return setErrorInternal(VBOX_E_INVALID_VM_STATE,
- COM_IIDOF(IConsole),
- getStaticComponentName(),
- (enmVMState == VMSTATE_RUNNING_LS) ? Utf8Str(tr("Cannot change drive during live migration")) : Utf8Str(tr("Cannot change drive during fault tolerant syncing")),
- false /*aWarning*/,
- true /*aLogIt*/);
-
- default:
- AssertMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED);
- }
+ AssertReturn(enmVMState == VMSTATE_SUSPENDED, VERR_INVALID_STATE);
/* Determine the base path for the device instance. */
PCFGMNODE pCtlInst;
@@ -4234,7 +4152,7 @@ DECLCALLBACK(int) Console::detachStorageDevice(Console *pConsole,
CFGMR3RemoveNode(pLunL0);
Utf8Str devicePath = Utf8StrFmt("%s/%u/LUN#%u", pcszDevice, uInstance, uLUN);
- pConsole->mapMediumAttachments.erase(devicePath);
+ pThis->mapMediumAttachments.erase(devicePath);
}
else
@@ -4242,32 +4160,6 @@ DECLCALLBACK(int) Console::detachStorageDevice(Console *pConsole,
CFGMR3Dump(pCtlInst);
- /*
- * Resume the VM if necessary.
- */
- if (fResume)
- {
- LogFlowFunc(("Resuming the VM...\n"));
- /* disable the callback to prevent Console-level state change */
- pConsole->mVMStateChangeCallbackDisabled = true;
- rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
- pConsole->mVMStateChangeCallbackDisabled = false;
- AssertRC(rc);
- if (RT_FAILURE(rc))
- {
- /* too bad, we failed. try to sync the console state with the VMM state */
- vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, pConsole);
- }
- /** @todo: if we failed with drive mount, then the VMR3Resume
- * error (if any) will be hidden from the caller. For proper reporting
- * of such multiple errors to the caller we need to enhance the
- * IVirtualBoxError interface. For now, give the first error the higher
- * priority.
- */
- if (RT_SUCCESS(rcRet))
- rcRet = rc;
- }
-
LogFlowFunc(("Returning %Rrc\n", rcRet));
return rcRet;
}
@@ -4507,13 +4399,21 @@ HRESULT Console::doNetworkAdapterChange(PUVM pUVM,
AssertComRCReturnRC(autoCaller.rc());
/*
+ * Suspend the VM first.
+ */
+ bool fResume = false;
+ int rc = suspendBeforeConfigChange(pUVM, NULL, &fResume);
+ if (FAILED(rc))
+ return rc;
+
+ /*
* Call worker in EMT, that's faster and safer than doing everything
* using VM3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait
* here to make requests from under the lock in order to serialize them.
*/
PVMREQ pReq;
int vrc = VMR3ReqCallU(pUVM, 0 /*idDstCpu*/, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
- (PFNRT)Console::changeNetworkAttachment, 6,
+ (PFNRT)changeNetworkAttachment, 6,
this, pUVM, pszDevice, uInstance, uLun, aNetworkAdapter);
if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc))
@@ -4525,6 +4425,9 @@ HRESULT Console::doNetworkAdapterChange(PUVM pUVM,
}
VMR3ReqFree(pReq);
+ if (fResume)
+ resumeAfterConfigChange(pUVM);
+
if (RT_SUCCESS(vrc))
{
LogFlowThisFunc(("Returns S_OK\n"));
@@ -4551,6 +4454,7 @@ HRESULT Console::doNetworkAdapterChange(PUVM pUVM,
*
* @thread EMT
* @note Locks the Console object for writing.
+ * @note The VM must not be running.
*/
DECLCALLBACK(int) Console::changeNetworkAttachment(Console *pThis,
PUVM pUVM,
@@ -4586,76 +4490,21 @@ DECLCALLBACK(int) Console::changeNetworkAttachment(Console *pThis,
Log(("pszDevice=%s uLun=%d uInstance=%d\n", pszDevice, uLun, uInstance));
/*
- * Suspend the VM first.
- *
- * The VM must not be running since it might have pending I/O to
- * the drive which is being changed.
+ * Check the VM for correct state.
*/
- bool fResume;
VMSTATE enmVMState = VMR3GetStateU(pUVM);
- switch (enmVMState)
- {
- case VMSTATE_RESETTING:
- case VMSTATE_RUNNING:
- {
- LogFlowFunc(("Suspending the VM...\n"));
- /* disable the callback to prevent Console-level state change */
- pThis->mVMStateChangeCallbackDisabled = true;
- int rc = VMR3Suspend(pUVM, VMSUSPENDREASON_RECONFIG);
- pThis->mVMStateChangeCallbackDisabled = false;
- AssertRCReturn(rc, rc);
- fResume = true;
- break;
- }
-
- case VMSTATE_SUSPENDED:
- case VMSTATE_CREATED:
- case VMSTATE_OFF:
- fResume = false;
- break;
-
- default:
- AssertLogRelMsgFailedReturn(("enmVMState=%d\n", enmVMState), VERR_ACCESS_DENIED);
- }
-
- int rc = VINF_SUCCESS;
- int rcRet = VINF_SUCCESS;
+ AssertReturn(enmVMState == VMSTATE_SUSPENDED, VERR_INVALID_STATE);
PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
PCFGMNODE pInst = CFGMR3GetChildF(CFGMR3GetRootU(pUVM), "Devices/%s/%d/", pszDevice, uInstance);
AssertRelease(pInst);
- rcRet = pThis->configNetwork(pszDevice, uInstance, uLun, aNetworkAdapter, pCfg, pLunL0, pInst,
- true /*fAttachDetach*/, false /*fIgnoreConnectFailure*/);
-
- /*
- * Resume the VM if necessary.
- */
- if (fResume)
- {
- LogFlowFunc(("Resuming the VM...\n"));
- /* disable the callback to prevent Console-level state change */
- pThis->mVMStateChangeCallbackDisabled = true;
- rc = VMR3Resume(pUVM, VMRESUMEREASON_RECONFIG);
- pThis->mVMStateChangeCallbackDisabled = false;
- AssertRC(rc);
- if (RT_FAILURE(rc))
- {
- /* too bad, we failed. try to sync the console state with the VMM state */
- vmstateChangeCallback(pUVM, VMSTATE_SUSPENDED, enmVMState, pThis);
- }
- /// @todo (r=dmik) if we failed with drive mount, then the VMR3Resume
- // error (if any) will be hidden from the caller. For proper reporting
- // of such multiple errors to the caller we need to enhance the
- // IVirtualBoxError interface. For now, give the first error the higher
- // priority.
- if (RT_SUCCESS(rcRet))
- rcRet = rc;
- }
+ int rc = pThis->configNetwork(pszDevice, uInstance, uLun, aNetworkAdapter, pCfg, pLunL0, pInst,
+ true /*fAttachDetach*/, false /*fIgnoreConnectFailure*/);
- LogFlowFunc(("Returning %Rrc\n", rcRet));
- return rcRet;
+ LogFlowFunc(("Returning %Rrc\n", rc));
+ return rc;
}
@@ -5703,23 +5552,11 @@ HRESULT Console::onlineMergeMedium(IMediumAttachment *aMediumAttachment,
AssertRCReturn(vrc2, E_FAIL);
}
- vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(),
- VMCPUID_ANY,
- (PFNRT)reconfigureMediumAttachment,
- 13,
- this,
- ptrVM.rawUVM(),
- pcszDevice,
- uInstance,
- enmBus,
- fUseHostIOCache,
- fBuiltinIOCache,
- true /* fSetupMerge */,
- aSourceIdx,
- aTargetIdx,
- aMediumAttachment,
- mMachineState,
- &rc);
+ vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY,
+ (PFNRT)reconfigureMediumAttachment, 13,
+ this, ptrVM.rawUVM(), pcszDevice, uInstance, enmBus, fUseHostIOCache,
+ fBuiltinIOCache, true /* fSetupMerge */, aSourceIdx, aTargetIdx,
+ aMediumAttachment, mMachineState, &rc);
/* error handling is after resuming the VM */
if (mMachineState == MachineState_DeletingSnapshotOnline)
@@ -5777,23 +5614,11 @@ HRESULT Console::onlineMergeMedium(IMediumAttachment *aMediumAttachment,
/* Update medium chain and state now, so that the VM can continue. */
rc = mControl->FinishOnlineMergeMedium();
- vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(),
- VMCPUID_ANY,
- (PFNRT)reconfigureMediumAttachment,
- 13,
- this,
- ptrVM.rawUVM(),
- pcszDevice,
- uInstance,
- enmBus,
- fUseHostIOCache,
- fBuiltinIOCache,
- false /* fSetupMerge */,
- 0 /* uMergeSource */,
- 0 /* uMergeTarget */,
- aMediumAttachment,
- mMachineState,
- &rc);
+ vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY,
+ (PFNRT)reconfigureMediumAttachment, 13,
+ this, ptrVM.rawUVM(), pcszDevice, uInstance, enmBus, fUseHostIOCache,
+ fBuiltinIOCache, false /* fSetupMerge */, 0 /* uMergeSource */,
+ 0 /* uMergeTarget */, aMediumAttachment, mMachineState, &rc);
/* error handling is after resuming the VM */
if (mMachineState == MachineState_DeletingSnapshotOnline)
@@ -8236,7 +8061,6 @@ HRESULT Console::attachUSBDevice(IUSBDevice *aHostDevice, ULONG aMaskedIfs)
(PFNRT)usbAttachCallback, 9,
this, ptrVM.rawUVM(), aHostDevice, uuid.raw(), fRemote,
Address.c_str(), pvRemoteBackend, portVersion, aMaskedIfs);
-
if (RT_SUCCESS(vrc))
{
/* Create a OUSBDevice and add it to the device list */
@@ -9461,7 +9285,7 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
/**
* Reconfigures a medium attachment (part of taking or deleting an online snapshot).
*
- * @param pConsole Reference to the console object.
+ * @param pThis Reference to the console object.
* @param pUVM The VM handle.
* @param lInstance The instance of the controller.
* @param pcszDevice The name of the controller type.
@@ -9475,7 +9299,7 @@ DECLCALLBACK(int) Console::powerUpThread(RTTHREAD Thread, void *pvUser)
* @return VBox status code.
*/
/* static */
-DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pConsole,
+DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pThis,
PUVM pUVM,
const char *pcszDevice,
unsigned uInstance,
@@ -9491,11 +9315,9 @@ DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pConsole,
{
LogFlowFunc(("pUVM=%p aMediumAtt=%p phrc=%p\n", pUVM, aMediumAtt, phrc));
- int rc;
HRESULT hrc;
Bstr bstr;
*phrc = S_OK;
-#define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertMsgFailed(("rc=%Rrc\n", rc)); return rc; } } while (0)
#define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%Rhrc (%#x)\n", hrc, hrc)); *phrc = hrc; return VERR_GENERAL_FAILURE; } } while (0)
/* Ignore attachments other than hard disks, since at the moment they are
@@ -9511,29 +9333,33 @@ DECLCALLBACK(int) Console::reconfigureMediumAttachment(Console *pConsole,
AssertReturn(pCtlInst, VERR_INTERNAL_ERROR);
/* Update the device instance configuration. */
- rc = pConsole->configMediumAttachment(pCtlInst,
- pcszDevice,
- uInstance,
- enmBus,
- fUseHostIOCache,
- fBuiltinIOCache,
- fSetupMerge,
- uMergeSource,
- uMergeTarget,
- aMediumAtt,
- aMachineState,
- phrc,
- true /* fAttachDetach */,
- false /* fForceUnmount */,
- false /* fHotplug */,
- pUVM,
- NULL /* paLedDevType */);
- /** @todo this dumps everything attached to this device instance, which
- * is more than necessary. Dumping the changed LUN would be enough. */
- CFGMR3Dump(pCtlInst);
- RC_CHECK();
+ PCFGMNODE pLunL0 = NULL;
+ int rc = pThis->configMediumAttachment(pCtlInst,
+ pcszDevice,
+ uInstance,
+ enmBus,
+ fUseHostIOCache,
+ fBuiltinIOCache,
+ fSetupMerge,
+ uMergeSource,
+ uMergeTarget,
+ aMediumAtt,
+ aMachineState,
+ phrc,
+ true /* fAttachDetach */,
+ false /* fForceUnmount */,
+ false /* fHotplug */,
+ pUVM,
+ NULL /* paLedDevType */,
+ &pLunL0);
+ /* Dump the changed LUN if possible, dump the complete device otherwise */
+ CFGMR3Dump(pLunL0 ? pLunL0 : pCtlInst);
+ if (RT_FAILURE(rc))
+ {
+ AssertMsgFailed(("rc=%Rrc\n", rc));
+ return rc;
+ }
-#undef RC_CHECK
#undef H
LogFlowFunc(("Returns success\n"));
@@ -9715,23 +9541,11 @@ DECLCALLBACK(int) Console::fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)
* don't release the lock since reconfigureMediumAttachment
* isn't going to need the Console lock.
*/
- vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(),
- VMCPUID_ANY,
- (PFNRT)reconfigureMediumAttachment,
- 13,
- that,
- ptrVM.rawUVM(),
- pcszDevice,
- lInstance,
- enmBus,
- fUseHostIOCache,
- fBuiltinIOCache,
- false /* fSetupMerge */,
- 0 /* uMergeSource */,
- 0 /* uMergeTarget */,
- atts[i],
- that->mMachineState,
- &rc);
+ vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY,
+ (PFNRT)reconfigureMediumAttachment, 13,
+ that, ptrVM.rawUVM(), pcszDevice, lInstance, enmBus, fUseHostIOCache,
+ fBuiltinIOCache, false /* fSetupMerge */, 0 /* uMergeSource */,
+ 0 /* uMergeTarget */, atts[i], that->mMachineState, &rc);
if (RT_FAILURE(vrc))
throw setErrorStatic(E_FAIL, Console::tr("%Rrc"), vrc);
if (FAILED(rc))
diff --git a/src/VBox/Main/src-client/ConsoleImpl2.cpp b/src/VBox/Main/src-client/ConsoleImpl2.cpp
index b762a06ef..78feac8fd 100644
--- a/src/VBox/Main/src-client/ConsoleImpl2.cpp
+++ b/src/VBox/Main/src-client/ConsoleImpl2.cpp
@@ -1924,7 +1924,8 @@ int Console::configConstructorInner(PUVM pUVM, PVM pVM, AutoWriteLock *pAlock)
false /* fForceUnmount */,
false /* fHotplug */,
pUVM,
- paLedDevType);
+ paLedDevType,
+ NULL /* ppLunL0 */);
if (RT_FAILURE(rc))
return rc;
}
@@ -3414,7 +3415,8 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
bool fForceUnmount,
bool fHotplug,
PUVM pUVM,
- DeviceType_T *paLedDevType)
+ DeviceType_T *paLedDevType,
+ PCFGMNODE *ppLunL0)
{
// InsertConfig* throws
try
@@ -3485,6 +3487,8 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst,
}
InsertConfigNode(pCtlInst, Utf8StrFmt("LUN#%u", uLUN).c_str(), &pLunL0);
+ if (ppLunL0)
+ *ppLunL0 = pLunL0;
PCFGMNODE pCfg = CFGMR3GetChild(pCtlInst, "Config");
if (pCfg)
diff --git a/src/VBox/Main/src-client/DisplayImpl.cpp b/src/VBox/Main/src-client/DisplayImpl.cpp
index b62708579..3477a07c2 100644
--- a/src/VBox/Main/src-client/DisplayImpl.cpp
+++ b/src/VBox/Main/src-client/DisplayImpl.cpp
@@ -4300,31 +4300,9 @@ void Display::handleCrHgsmiControlCompletion(int32_t result, uint32_t u32Functio
mpDrv->pVBVACallbacks->pfnCrHgsmiControlCompleteAsync(mpDrv->pVBVACallbacks, (PVBOXVDMACMD_CHROMIUM_CTL)pParam->u.pointer.addr, result);
}
-int Display::handleCrCmdNotifyCmds()
-{
- int rc = VERR_INVALID_FUNCTION;
-
- if (mhCrOglSvc)
- {
- VBOXHGCMSVCPARM dummy;
- VMMDev *pVMMDev = mParent->getVMMDev();
- if (pVMMDev)
- {
- /* no completion callback is specified with this call,
- * the CrOgl code will complete the CrHgsmi command once it processes it */
- rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS, &dummy, NULL, NULL);
- AssertRC(rc);
- }
- else
- rc = VERR_INVALID_STATE;
- }
-
- return rc;
-}
-
void Display::handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
{
- int rc = VERR_INVALID_FUNCTION;
+ int rc = VERR_NOT_SUPPORTED;
VBOXHGCMSVCPARM parm;
parm.type = VBOX_HGCM_SVC_PARM_PTR;
parm.u.pointer.addr = pCmd;
@@ -4352,7 +4330,7 @@ void Display::handleCrHgsmiCommandProcess(PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32
void Display::handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl)
{
- int rc = VERR_INVALID_FUNCTION;
+ int rc = VERR_NOT_SUPPORTED;
VBOXHGCMSVCPARM parm;
parm.type = VBOX_HGCM_SVC_PARM_PTR;
parm.u.pointer.addr = pCtl;
@@ -4376,13 +4354,6 @@ void Display::handleCrHgsmiControlProcess(PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32
handleCrHgsmiControlCompletion(rc, SHCRGL_HOST_FN_CRHGSMI_CTL, &parm);
}
-DECLCALLBACK(int) Display::displayCrCmdNotifyCmds(PPDMIDISPLAYCONNECTOR pInterface)
-{
- PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
-
- return pDrv->pDisplay->handleCrCmdNotifyCmds();
-}
-
DECLCALLBACK(void) Display::displayCrHgsmiCommandProcess(PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd)
{
PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
@@ -4411,6 +4382,48 @@ DECLCALLBACK(void) Display::displayCrHgsmiControlCompletion(int32_t result, uint
}
#endif
+DECLCALLBACK(void) Display::displayCrHgcmCtlSubmitCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
+{
+ VBOXCRCMDCTL *pCmd = (VBOXCRCMDCTL*)pParam->u.pointer.addr;
+ if (pCmd->pfnInternal)
+ ((PFNCRCTLCOMPLETION)pCmd->pfnInternal)(pCmd, pParam->u.pointer.size, result, pvContext);
+}
+
+int Display::handleCrHgcmCtlSubmit(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
+ PFNCRCTLCOMPLETION pfnCompletion,
+ void *pvCompletion)
+{
+ VMMDev *pVMMDev = mParent->getVMMDev();
+ if (!pVMMDev)
+ {
+ AssertMsgFailed(("no vmmdev\n"));
+ return VERR_INVALID_STATE;
+ }
+
+ Assert(mhCrOglSvc);
+ VBOXHGCMSVCPARM parm;
+ parm.type = VBOX_HGCM_SVC_PARM_PTR;
+ parm.u.pointer.addr = pCmd;
+ parm.u.pointer.size = cbCmd;
+
+ pCmd->pfnInternal = (void(*)())pfnCompletion;
+ int rc = pVMMDev->hgcmHostFastCallAsync(mhCrOglSvc, SHCRGL_HOST_FN_CTL, &parm, displayCrHgcmCtlSubmitCompletion, pvCompletion);
+ if (!RT_SUCCESS(rc))
+ AssertMsgFailed(("hgcmHostFastCallAsync failed rc %n", rc));
+
+ return rc;
+}
+
+DECLCALLBACK(int) Display::displayCrHgcmCtlSubmit(PPDMIDISPLAYCONNECTOR pInterface,
+ struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
+ PFNCRCTLCOMPLETION pfnCompletion,
+ void *pvCompletion)
+{
+ PDRVMAINDISPLAY pDrv = PDMIDISPLAYCONNECTOR_2_MAINDISPLAY(pInterface);
+ Display *pThis = pDrv->pDisplay;
+ return pThis->handleCrHgcmCtlSubmit(pCmd, cbCmd, pfnCompletion, pvCompletion);
+}
+
#if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
DECLCALLBACK(void) Display::displayCrAsyncCmdCompletion(int32_t result, uint32_t u32Function, PVBOXHGCMSVCPARM pParam, void *pvContext)
{
@@ -5034,10 +5047,10 @@ DECLCALLBACK(int) Display::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint
pThis->IConnector.pfnVHWACommandProcess = Display::displayVHWACommandProcess;
#endif
#ifdef VBOX_WITH_CRHGSMI
- pThis->IConnector.pfnCrCmdNotifyCmds = Display::displayCrCmdNotifyCmds;
pThis->IConnector.pfnCrHgsmiCommandProcess = Display::displayCrHgsmiCommandProcess;
pThis->IConnector.pfnCrHgsmiControlProcess = Display::displayCrHgsmiControlProcess;
#endif
+ pThis->IConnector.pfnCrHgcmCtlSubmit = Display::displayCrHgcmCtlSubmit;
#ifdef VBOX_WITH_HGSMI
pThis->IConnector.pfnVBVAEnable = Display::displayVBVAEnable;
pThis->IConnector.pfnVBVADisable = Display::displayVBVADisable;
diff --git a/src/VBox/Main/src-client/GuestFileImpl.cpp b/src/VBox/Main/src-client/GuestFileImpl.cpp
index 4bd3c5737..8a0ce53e2 100644
--- a/src/VBox/Main/src-client/GuestFileImpl.cpp
+++ b/src/VBox/Main/src-client/GuestFileImpl.cpp
@@ -160,7 +160,7 @@ int GuestFile::init(Console *pConsole, GuestSession *pSession,
mData.mOpenInfo = openInfo;
unconst(mEventSource).createObject();
- HRESULT hr = mEventSource->init(static_cast<IGuestFile*>(this));
+ HRESULT hr = mEventSource->init();
if (FAILED(hr))
vrc = VERR_COM_UNEXPECTED;
}
diff --git a/src/VBox/Main/src-client/GuestImpl.cpp b/src/VBox/Main/src-client/GuestImpl.cpp
index e41a6f6f2..41469b0c4 100644
--- a/src/VBox/Main/src-client/GuestImpl.cpp
+++ b/src/VBox/Main/src-client/GuestImpl.cpp
@@ -111,7 +111,7 @@ HRESULT Guest::init(Console *aParent)
#ifdef VBOX_WITH_GUEST_CONTROL
hr = unconst(mEventSource).createObject();
if (SUCCEEDED(hr))
- hr = mEventSource->init(static_cast<IGuest*>(this));
+ hr = mEventSource->init();
#else
hr = S_OK;
#endif
diff --git a/src/VBox/Main/src-client/GuestProcessImpl.cpp b/src/VBox/Main/src-client/GuestProcessImpl.cpp
index cfd2d1dcd..4ccf1e44d 100644
--- a/src/VBox/Main/src-client/GuestProcessImpl.cpp
+++ b/src/VBox/Main/src-client/GuestProcessImpl.cpp
@@ -188,7 +188,7 @@ int GuestProcess::init(Console *aConsole, GuestSession *aSession,
vrc = VERR_NO_MEMORY;
else
{
- hr = mEventSource->init(static_cast<IGuestProcess*>(this));
+ hr = mEventSource->init();
if (FAILED(hr))
vrc = VERR_COM_UNEXPECTED;
}
diff --git a/src/VBox/Main/src-client/GuestSessionImpl.cpp b/src/VBox/Main/src-client/GuestSessionImpl.cpp
index 31de6b105..433ac056b 100644
--- a/src/VBox/Main/src-client/GuestSessionImpl.cpp
+++ b/src/VBox/Main/src-client/GuestSessionImpl.cpp
@@ -211,7 +211,7 @@ int GuestSession::init(Guest *pGuest, const GuestSessionStartupInfo &ssInfo,
rc = VERR_NO_MEMORY;
else
{
- hr = mEventSource->init(static_cast<IGuestSession*>(this));
+ hr = mEventSource->init();
if (FAILED(hr))
rc = VERR_COM_UNEXPECTED;
}
diff --git a/src/VBox/Main/src-client/KeyboardImpl.cpp b/src/VBox/Main/src-client/KeyboardImpl.cpp
index b8010e7ae..74154daca 100644
--- a/src/VBox/Main/src-client/KeyboardImpl.cpp
+++ b/src/VBox/Main/src-client/KeyboardImpl.cpp
@@ -112,7 +112,7 @@ HRESULT Keyboard::init(Console *aParent)
unconst(mParent) = aParent;
unconst(mEventSource).createObject();
- HRESULT rc = mEventSource->init(static_cast<IKeyboard*>(this));
+ HRESULT rc = mEventSource->init();
AssertComRCReturnRC(rc);
/* Confirm a successful initialization */
diff --git a/src/VBox/Main/src-client/MouseImpl.cpp b/src/VBox/Main/src-client/MouseImpl.cpp
index 94a79eb41..652f2df35 100644
--- a/src/VBox/Main/src-client/MouseImpl.cpp
+++ b/src/VBox/Main/src-client/MouseImpl.cpp
@@ -112,7 +112,7 @@ HRESULT Mouse::init (ConsoleMouseInterface *parent)
unconst(mParent) = parent;
unconst(mEventSource).createObject();
- HRESULT rc = mEventSource->init(static_cast<IMouse*>(this));
+ HRESULT rc = mEventSource->init();
AssertComRCReturnRC(rc);
mMouseEvent.init(mEventSource, VBoxEventType_OnGuestMouse,
0, 0, 0, 0, 0, 0);
diff --git a/src/VBox/Main/src-client/VirtualBoxClientImpl.cpp b/src/VBox/Main/src-client/VirtualBoxClientImpl.cpp
index c421c9304..0e2405af5 100644
--- a/src/VBox/Main/src-client/VirtualBoxClientImpl.cpp
+++ b/src/VBox/Main/src-client/VirtualBoxClientImpl.cpp
@@ -81,7 +81,7 @@ HRESULT VirtualBoxClient::init()
rc = unconst(mData.m_pEventSource).createObject();
AssertComRCReturnRC(rc);
- rc = mData.m_pEventSource->init(static_cast<IVirtualBoxClient *>(this));
+ rc = mData.m_pEventSource->init();
AssertComRCReturnRC(rc);
/* Setting up the VBoxSVC watcher thread. If anything goes wrong here it
diff --git a/src/VBox/Main/src-server/ApplianceImpl.cpp b/src/VBox/Main/src-server/ApplianceImpl.cpp
index 4c498fd6c..8d1e60141 100644
--- a/src/VBox/Main/src-server/ApplianceImpl.cpp
+++ b/src/VBox/Main/src-server/ApplianceImpl.cpp
@@ -1530,8 +1530,10 @@ void VirtualSystemDescription::addEntry(VirtualSystemDescriptionType_T aType,
= vsde.strExtraConfigCurrent
= strExtraConfig;
vsde.ulSizeMB = ulSizeMB;
+ vsde.skipIt = false;
m->llDescriptions.push_back(vsde);
+
}
/**
diff --git a/src/VBox/Main/src-server/ApplianceImplExport.cpp b/src/VBox/Main/src-server/ApplianceImplExport.cpp
index 5980e1c6b..c8c5718f9 100644
--- a/src/VBox/Main/src-server/ApplianceImplExport.cpp
+++ b/src/VBox/Main/src-server/ApplianceImplExport.cpp
@@ -607,7 +607,13 @@ STDMETHODIMP Appliance::Write(IN_BSTR format, ComSafeArrayIn(ImportOptions_T, op
++it)
{
ComObjPtr<VirtualSystemDescription> vsdescThis = (*it);
- vsdescThis->removeByType(VirtualSystemDescriptionType_CDROM);
+ std::list<VirtualSystemDescriptionEntry*> skipped = vsdescThis->findByType(VirtualSystemDescriptionType_CDROM);
+ std::list<VirtualSystemDescriptionEntry*>:: iterator pItSkipped = skipped.begin();
+ while (pItSkipped != skipped.end())
+ {
+ (*pItSkipped)->skipIt = true;
+ ++pItSkipped;
+ }
}
}
@@ -886,7 +892,8 @@ void Appliance::buildXML(AutoWriteLockBase& writeLock,
Bstr bstrSrcFilePath(strSrcFilePath);
//skip empty Medium. There are no information to add into section <References> or <DiskSection>
- if (strSrcFilePath.isEmpty())
+ if (strSrcFilePath.isEmpty() ||
+ pDiskEntry->skipIt == true)
continue;
// Do NOT check here whether the file exists. FindMedium will figure
@@ -1516,7 +1523,8 @@ void Appliance::buildXMLForOneVirtualSystem(AutoWriteLockBase& writeLock,
lAutomaticAllocation = 1;
//skip empty Medium. There are no information to add into section <References> or <DiskSection>
- if (desc.strVBoxCurrent.isNotEmpty())
+ if (desc.strVBoxCurrent.isNotEmpty() &&
+ desc.skipIt == false)
{
// the following references the "<Disks>" XML block
strHostResource = Utf8StrFmt("/disk/%s", strDiskID.c_str());
@@ -2091,7 +2099,8 @@ HRESULT Appliance::writeFSImpl(TaskOVF *pTask, AutoWriteLockBase& writeLock, PVD
const Utf8Str &strSrcFilePath = pDiskEntry->strVBoxCurrent;
//skip empty Medium. In common, It's may be empty CD/DVD
- if (strSrcFilePath.isEmpty())
+ if (strSrcFilePath.isEmpty() ||
+ pDiskEntry->skipIt == true)
continue;
// Do NOT check here whether the file exists. findHardDisk will
diff --git a/src/VBox/Main/src-server/HostDnsService.cpp b/src/VBox/Main/src-server/HostDnsService.cpp
index d4cd3a0f4..011528fba 100644
--- a/src/VBox/Main/src-server/HostDnsService.cpp
+++ b/src/VBox/Main/src-server/HostDnsService.cpp
@@ -288,7 +288,7 @@ HRESULT HostDnsMonitorProxy::GetDomainName(BSTR *aDomainName)
if (m->fModified)
updateInfo();
- LogRel(("HostDnsMonitorProxy::GetDomainName:%s\n", m->info->domain.c_str()));
+ LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n", m->info->domain.c_str()));
Utf8Str(m->info->domain.c_str()).cloneTo(aDomainName);
@@ -355,7 +355,7 @@ static void dumpHostDnsInformation(const HostDnsInformation& info)
static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
{
- int i = 0;
+ int i = 1;
for (std::vector<std::string>::const_iterator it = v.begin();
it != v.end();
++it, ++i)
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index b8eea6f14..d79059174 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -12858,28 +12858,6 @@ HRESULT SessionMachine::init(Machine *aMachine)
{
unconst(mNetworkAdapters[slot]).createObject();
mNetworkAdapters[slot]->init(this, aMachine->mNetworkAdapters[slot]);
-
- NetworkAttachmentType_T type;
- HRESULT hrc;
- hrc = mNetworkAdapters[slot]->COMGETTER(AttachmentType)(&type);
- if ( SUCCEEDED(hrc)
- && type == NetworkAttachmentType_NATNetwork)
- {
- Bstr name;
- hrc = mNetworkAdapters[slot]->COMGETTER(NATNetwork)(name.asOutParam());
- if (SUCCEEDED(hrc))
- {
- LogRel(("VM '%s' starts using NAT network '%ls'\n",
- mUserData->s.strName.c_str(), name.raw()));
- aMachine->lockHandle()->unlockWrite();
- mParent->natNetworkRefInc(name.raw());
-#ifdef RT_LOCK_STRICT
- aMachine->lockHandle()->lockWrite(RT_SRC_POS);
-#else
- aMachine->lockHandle()->lockWrite();
-#endif
- }
- }
}
/* create another bandwidth control object that will be mutable */
@@ -12892,6 +12870,8 @@ HRESULT SessionMachine::init(Machine *aMachine)
/* Confirm a successful initialization when it's the case */
autoInitSpan.setSucceeded();
+ miNATNetworksStarted = 0;
+
LogFlowThisFuncLeave();
return rc;
}
@@ -13071,24 +13051,29 @@ void SessionMachine::uninit(Uninit::Reason aReason)
mData->mSession.mRemoteControls.clear();
}
- for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
+ /* Remove all references to the NAT network service. The service will stop
+ * if all references (also from other VMs) are removed. */
+ for (; miNATNetworksStarted > 0; miNATNetworksStarted--)
{
- NetworkAttachmentType_T type;
- HRESULT hrc;
-
- hrc = mNetworkAdapters[slot]->COMGETTER(AttachmentType)(&type);
- if ( SUCCEEDED(hrc)
- && type == NetworkAttachmentType_NATNetwork)
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
{
- Bstr name;
- hrc = mNetworkAdapters[slot]->COMGETTER(NATNetwork)(name.asOutParam());
- if (SUCCEEDED(hrc))
+ NetworkAttachmentType_T type;
+ HRESULT hrc;
+
+ hrc = mNetworkAdapters[slot]->COMGETTER(AttachmentType)(&type);
+ if ( SUCCEEDED(hrc)
+ && type == NetworkAttachmentType_NATNetwork)
{
- multilock.release();
- LogRel(("VM '%s' stops using NAT network '%ls'\n",
- mUserData->s.strName.c_str(), name.raw()));
- mParent->natNetworkRefDec(name.raw());
- multilock.acquire();
+ Bstr name;
+ hrc = mNetworkAdapters[slot]->COMGETTER(NATNetwork)(name.asOutParam());
+ if (SUCCEEDED(hrc))
+ {
+ multilock.release();
+ LogRel(("VM '%s' stops using NAT network '%ls'\n",
+ mUserData->s.strName.c_str(), name.raw()));
+ mParent->natNetworkRefDec(name.raw());
+ multilock.acquire();
+ }
}
}
}
@@ -13261,6 +13246,37 @@ STDMETHODIMP SessionMachine::BeginPowerUp(IProgress *aProgress)
if (!mData->mSession.mProgress.isNull())
mData->mSession.mProgress->setOtherProgressObject(aProgress);
+ /* If we didn't reference the NAT network service yet, add a reference to
+ * force a start */
+ if (miNATNetworksStarted < 1)
+ {
+ for (ULONG slot = 0; slot < mNetworkAdapters.size(); slot++)
+ {
+ NetworkAttachmentType_T type;
+ HRESULT hrc;
+ hrc = mNetworkAdapters[slot]->COMGETTER(AttachmentType)(&type);
+ if ( SUCCEEDED(hrc)
+ && type == NetworkAttachmentType_NATNetwork)
+ {
+ Bstr name;
+ hrc = mNetworkAdapters[slot]->COMGETTER(NATNetwork)(name.asOutParam());
+ if (SUCCEEDED(hrc))
+ {
+ LogRel(("VM '%s' starts using NAT network '%ls'\n",
+ mUserData->s.strName.c_str(), name.raw()));
+ mPeer->lockHandle()->unlockWrite();
+ mParent->natNetworkRefInc(name.raw());
+#ifdef RT_LOCK_STRICT
+ mPeer->lockHandle()->lockWrite(RT_SRC_POS);
+#else
+ mPeer->lockHandle()->lockWrite();
+#endif
+ }
+ }
+ }
+ miNATNetworksStarted++;
+ }
+
LogFlowThisFunc(("returns S_OK.\n"));
return S_OK;
}
diff --git a/src/VBox/Main/src-server/NATNetworkImpl.cpp b/src/VBox/Main/src-server/NATNetworkImpl.cpp
index c419420fb..653272503 100644
--- a/src/VBox/Main/src-server/NATNetworkImpl.cpp
+++ b/src/VBox/Main/src-server/NATNetworkImpl.cpp
@@ -154,7 +154,7 @@ HRESULT NATNetwork::init(VirtualBox *aVirtualBox, IN_BSTR aName)
HRESULT hrc = unconst(m->pEventSource).createObject();
if (FAILED(hrc)) throw hrc;
- hrc = m->pEventSource->init(static_cast<INATNetwork *>(this));
+ hrc = m->pEventSource->init();
if (FAILED(hrc)) throw hrc;
/* Confirm a successful initialization */
@@ -209,7 +209,7 @@ HRESULT NATNetwork::init(VirtualBox *aVirtualBox,
HRESULT hrc = unconst(m->pEventSource).createObject();
if (FAILED(hrc)) throw hrc;
- hrc = m->pEventSource->init(static_cast<INATNetwork *>(this));
+ hrc = m->pEventSource->init();
if (FAILED(hrc)) throw hrc;
autoInitSpan.setSucceeded();
diff --git a/src/VBox/Main/src-server/VirtualBoxImpl.cpp b/src/VBox/Main/src-server/VirtualBoxImpl.cpp
index e19e1f697..7c3192363 100644
--- a/src/VBox/Main/src-server/VirtualBoxImpl.cpp
+++ b/src/VBox/Main/src-server/VirtualBoxImpl.cpp
@@ -509,7 +509,7 @@ HRESULT VirtualBox::init()
/* events */
if (SUCCEEDED(rc = unconst(m->pEventSource).createObject()))
- rc = m->pEventSource->init(static_cast<IVirtualBox*>(this));
+ rc = m->pEventSource->init();
if (FAILED(rc)) throw rc;
#ifdef VBOX_WITH_EXTPACK
@@ -807,7 +807,11 @@ void VirtualBox::uninit()
LogFlowThisFunc(("Releasing event source...\n"));
if (m->pEventSource)
{
- // we don't perform uninit() as it's possible that some pending event refers to this source
+ // Must uninit the event source here, because it makes no sense that
+ // it survives longer than the base object. If someone gets an event
+ // with such an event source then that's life and it has to be dealt
+ // with appropriately on the API client side.
+ m->pEventSource->uninit();
unconst(m->pEventSource).setNull();
}
diff --git a/src/VBox/Main/src-server/darwin/iokit.cpp b/src/VBox/Main/src-server/darwin/iokit.cpp
index 7a7b1059f..69c572f27 100644
--- a/src/VBox/Main/src-server/darwin/iokit.cpp
+++ b/src/VBox/Main/src-server/darwin/iokit.cpp
@@ -8,7 +8,7 @@
*/
/*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -1354,7 +1354,7 @@ PDARWINDVD DarwinGetDVDDrives(void)
if (*pszVendor && *pszProduct)
RTStrPrintf(szName, sizeof(szName), "%s %s (#%u)", pszVendor, pszProduct, i);
else
- RTStrPrintf(szName, sizeof(szName), "%s %s (#%u)", *pszVendor ? pszVendor : pszProduct, i);
+ RTStrPrintf(szName, sizeof(szName), "%s (#%u)", *pszVendor ? pszVendor : pszProduct, i);
break;
}
}