diff options
Diffstat (limited to 'src/VBox/Main/src-client/SessionImpl.cpp')
-rw-r--r-- | src/VBox/Main/src-client/SessionImpl.cpp | 599 |
1 files changed, 254 insertions, 345 deletions
diff --git a/src/VBox/Main/src-client/SessionImpl.cpp b/src/VBox/Main/src-client/SessionImpl.cpp index 5c030550..6d2cbbd0 100644 --- a/src/VBox/Main/src-client/SessionImpl.cpp +++ b/src/VBox/Main/src-client/SessionImpl.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2012 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -15,17 +15,10 @@ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ -#ifdef VBOX_WITH_SYS_V_IPC_SESSION_WATCHER -# include <errno.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <sys/ipc.h> -# include <sys/sem.h> -#endif - #include "SessionImpl.h" #include "ConsoleImpl.h" #include "Global.h" +#include "ClientTokenHolder.h" #include "AutoCaller.h" #include "Logging.h" @@ -33,11 +26,6 @@ #include <VBox/err.h> #include <iprt/process.h> -#if defined(RT_OS_WINDOWS) || defined (RT_OS_OS2) -/** VM IPC mutex holder thread */ -static DECLCALLBACK(int) IPCMutexHolderThread(RTTHREAD Thread, void *pvUser); -#endif - /** * Local macro to check whether the session is open and return an error if not. * @note Don't forget to do |Auto[Reader]Lock alock (this);| before using this @@ -89,17 +77,7 @@ HRESULT Session::init() mState = SessionState_Unlocked; mType = SessionType_Null; -#if defined(RT_OS_WINDOWS) - mIPCSem = NULL; - mIPCThreadSem = NULL; -#elif defined(RT_OS_OS2) - mIPCThread = NIL_RTTHREAD; - mIPCThreadSem = NIL_RTSEMEVENT; -#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) - mIPCSem = -1; -#else -# error "Port me!" -#endif + mClientTokenHolder = NULL; /* Confirm a successful initialization when it's the case */ autoInitSpan.setSucceeded(); @@ -186,16 +164,21 @@ STDMETHODIMP Session::COMGETTER(Machine)(IMachine **aMachine) CHECK_OPEN(); HRESULT rc; +#ifndef VBOX_COM_INPROC_API_CLIENT if (mConsole) rc = mConsole->machine().queryInterfaceTo(aMachine); else +#endif rc = mRemoteMachine.queryInterfaceTo(aMachine); if (FAILED(rc)) { /** @todo VBox 3.3: replace E_FAIL with rc here. */ +#ifndef VBOX_COM_INPROC_API_CLIENT if (mConsole) setError(E_FAIL, tr("Failed to query the session machine (%Rhrc)"), rc); - else if (FAILED_DEAD_INTERFACE(rc)) + else +#endif + if (FAILED_DEAD_INTERFACE(rc)) setError(E_FAIL, tr("Peer process crashed")); else setError(E_FAIL, tr("Failed to query the remote session machine (%Rhrc)"), rc); @@ -216,17 +199,22 @@ STDMETHODIMP Session::COMGETTER(Console)(IConsole **aConsole) CHECK_OPEN(); HRESULT rc; +#ifndef VBOX_COM_INPROC_API_CLIENT if (mConsole) rc = mConsole.queryInterfaceTo(aConsole); else +#endif rc = mRemoteConsole.queryInterfaceTo(aConsole); if (FAILED(rc)) { /** @todo VBox 3.3: replace E_FAIL with rc here. */ +#ifndef VBOX_COM_INPROC_API_CLIENT if (mConsole) setError(E_FAIL, tr("Failed to query the console (%Rhrc)"), rc); - else if (FAILED_DEAD_INTERFACE(rc)) + else +#endif + if (FAILED_DEAD_INTERFACE(rc)) setError(E_FAIL, tr("Peer process crashed")); else setError(E_FAIL, tr("Failed to query the remote console (%Rhrc)"), rc); @@ -283,6 +271,7 @@ STDMETHODIMP Session::GetRemoteConsole(IConsole **aConsole) AssertReturn(mState != SessionState_Unlocked, VBOX_E_INVALID_VM_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertMsgReturn(mType == SessionType_WriteLock && !!mConsole, ("This is not a direct session!\n"), VBOX_E_INVALID_OBJECT_STATE); @@ -297,9 +286,20 @@ STDMETHODIMP Session::GetRemoteConsole(IConsole **aConsole) LogFlowThisFuncLeave(); return S_OK; + +#else /* VBOX_COM_INPROC_API_CLIENT */ + AssertFailed(); + return VBOX_E_INVALID_OBJECT_STATE; +#endif /* VBOX_COM_INPROC_API_CLIENT */ } -STDMETHODIMP Session::AssignMachine(IMachine *aMachine, LockType_T aLockType) +#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER +STDMETHODIMP Session::AssignMachine(IMachine *aMachine, LockType_T aLockType, + IN_BSTR aTokenId) +#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */ +STDMETHODIMP Session::AssignMachine(IMachine *aMachine, LockType_T aLockType, + IToken *aToken) +#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */ { LogFlowThisFuncEnter(); LogFlowThisFunc(("aMachine=%p\n", aMachine)); @@ -327,19 +327,46 @@ STDMETHODIMP Session::AssignMachine(IMachine *aMachine, LockType_T aLockType) return S_OK; } - HRESULT rc = E_FAIL; - /* query IInternalMachineControl interface */ mControl = aMachine; AssertReturn(!!mControl, E_FAIL); - rc = mConsole.createObject(); +#ifndef VBOX_COM_INPROC_API_CLIENT + HRESULT rc = mConsole.createObject(); AssertComRCReturn(rc, rc); rc = mConsole->init(aMachine, mControl, aLockType); AssertComRCReturn(rc, rc); +#else + HRESULT rc = S_OK; + mRemoteMachine = aMachine; +#endif - rc = grabIPCSemaphore(); +#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER + Utf8Str strTokenId(aTokenId); + Assert(!strTokenId.isEmpty()); +#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + AssertPtr(aToken); +#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + /* create the machine client token */ + try + { +#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER + mClientTokenHolder = new ClientTokenHolder(strTokenId); +#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + mClientTokenHolder = new ClientTokenHolder(aToken); +#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */ + if (!mClientTokenHolder->isReady()) + { + delete mClientTokenHolder; + mClientTokenHolder = NULL; + rc = E_FAIL; + } + } + catch (std::bad_alloc &) + { + rc = E_OUTOFMEMORY; + } /* * Reference the VirtualBox object to ensure the server is up @@ -357,11 +384,13 @@ STDMETHODIMP Session::AssignMachine(IMachine *aMachine, LockType_T aLockType) { /* some cleanup */ mControl.setNull(); +#ifndef VBOX_COM_INPROC_API_CLIENT if (!mConsole.isNull()) { mConsole->uninit(); mConsole.setNull(); } +#endif } LogFlowThisFunc(("rc=%08X\n", rc)); @@ -469,9 +498,13 @@ STDMETHODIMP Session::UpdateMachineState(MachineState_T aMachineState) AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); AssertReturn(!mControl.isNull(), E_FAIL); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(!mConsole.isNull(), E_FAIL); return mConsole->updateMachineState(aMachineState); +#else + return S_OK; +#endif } STDMETHODIMP Session::Uninitialize() @@ -495,10 +528,11 @@ STDMETHODIMP Session::Uninitialize() return S_OK; } -#ifndef DEBUG_andy /* Don't bug me -- now time to fix this at the moment. */ - AssertReturn(mState == SessionState_Locked || - mState == SessionState_Spawning, VBOX_E_INVALID_VM_STATE); -#endif + AssertMsgReturn( mState == SessionState_Locked + || mState == SessionState_Spawning, + ("Session is in wrong state (%ld), expected locked (%ld) or spawning (%ld)\n", + mState, SessionState_Locked, SessionState_Spawning), + VBOX_E_INVALID_VM_STATE); /* close ourselves */ rc = unlockMachine(false /* aFinalRelease */, true /* aFromServer */); @@ -533,9 +567,13 @@ STDMETHODIMP Session::OnNetworkAdapterChange(INetworkAdapter *networkAdapter, BO AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onNetworkAdapterChange(networkAdapter, changeAdapter); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnSerialPortChange(ISerialPort *serialPort) @@ -548,9 +586,13 @@ STDMETHODIMP Session::OnSerialPortChange(ISerialPort *serialPort) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onSerialPortChange(serialPort); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnParallelPortChange(IParallelPort *parallelPort) @@ -563,9 +605,13 @@ STDMETHODIMP Session::OnParallelPortChange(IParallelPort *parallelPort) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onParallelPortChange(parallelPort); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnStorageControllerChange() @@ -578,9 +624,13 @@ STDMETHODIMP Session::OnStorageControllerChange() AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onStorageControllerChange(); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce) @@ -593,9 +643,13 @@ STDMETHODIMP Session::OnMediumChange(IMediumAttachment *aMediumAttachment, BOOL AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onMediumChange(aMediumAttachment, aForce); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnCPUChange(ULONG aCPU, BOOL aRemove) @@ -608,9 +662,13 @@ STDMETHODIMP Session::OnCPUChange(ULONG aCPU, BOOL aRemove) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onCPUChange(aCPU, aRemove); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnCPUExecutionCapChange(ULONG aExecutionCap) @@ -623,9 +681,13 @@ STDMETHODIMP Session::OnCPUExecutionCapChange(ULONG aExecutionCap) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onCPUExecutionCapChange(aExecutionCap); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnVRDEServerChange(BOOL aRestart) @@ -638,9 +700,32 @@ STDMETHODIMP Session::OnVRDEServerChange(BOOL aRestart) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onVRDEServerChange(aRestart); +#else + return S_OK; +#endif +} + +STDMETHODIMP Session::OnVideoCaptureChange() +{ + LogFlowThisFunc(("\n")); + + AutoCaller autoCaller(this); + AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); + + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); + AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); + AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT + AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); + + return mConsole->onVideoCaptureChange(); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnUSBControllerChange() @@ -653,9 +738,13 @@ STDMETHODIMP Session::OnUSBControllerChange() AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onUSBControllerChange(); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnSharedFolderChange(BOOL aGlobal) @@ -668,9 +757,13 @@ STDMETHODIMP Session::OnSharedFolderChange(BOOL aGlobal) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onSharedFolderChange(aGlobal); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnClipboardModeChange(ClipboardMode_T aClipboardMode) @@ -683,9 +776,13 @@ STDMETHODIMP Session::OnClipboardModeChange(ClipboardMode_T aClipboardMode) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onClipboardModeChange(aClipboardMode); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode) @@ -697,9 +794,13 @@ STDMETHODIMP Session::OnDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onDragAndDropModeChange(aDragAndDropMode); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnUSBDeviceAttach(IUSBDevice *aDevice, @@ -714,9 +815,13 @@ STDMETHODIMP Session::OnUSBDeviceAttach(IUSBDevice *aDevice, AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onUSBDeviceAttach(aDevice, aError, aMaskedIfs); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnUSBDeviceDetach(IN_BSTR aId, @@ -730,9 +835,13 @@ STDMETHODIMP Session::OnUSBDeviceDetach(IN_BSTR aId, AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onUSBDeviceDetach(aId, aError); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId) @@ -743,7 +852,9 @@ STDMETHODIMP Session::OnShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); +#endif if (mState != SessionState_Locked) { @@ -756,7 +867,11 @@ STDMETHODIMP Session::OnShowWindow(BOOL aCheck, BOOL *aCanShow, LONG64 *aWinId) return aCheck ? S_OK : E_FAIL; } +#ifndef VBOX_COM_INPROC_API_CLIENT return mConsole->onShowWindow(aCheck, aCanShow, aWinId); +#else + return S_OK; +#endif } STDMETHODIMP Session::OnBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup) @@ -769,12 +884,16 @@ STDMETHODIMP Session::OnBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); return mConsole->onBandwidthGroupChange(aBandwidthGroup); +#else + return S_OK; +#endif } -STDMETHODIMP Session::OnStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove) +STDMETHODIMP Session::OnStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove, BOOL aSilent) { LogFlowThisFunc(("\n")); @@ -784,15 +903,20 @@ STDMETHODIMP Session::OnStorageDeviceChange(IMediumAttachment *aMediumAttachment AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); - return mConsole->onStorageDeviceChange(aMediumAttachment, aRemove); + return mConsole->onStorageDeviceChange(aMediumAttachment, aRemove, aSilent); +#else + return S_OK; +#endif } STDMETHODIMP Session::AccessGuestProperty(IN_BSTR aName, IN_BSTR aValue, IN_BSTR aFlags, BOOL aIsSetter, BSTR *aRetValue, LONG64 *aRetTimestamp, BSTR *aRetFlags) { #ifdef VBOX_WITH_GUEST_PROPS +# ifndef VBOX_COM_INPROC_API_CLIENT AutoCaller autoCaller(this); AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); @@ -810,10 +934,10 @@ STDMETHODIMP Session::AccessGuestProperty(IN_BSTR aName, IN_BSTR aValue, IN_BSTR return E_POINTER; /* aValue can be NULL for a setter call if the property is to be deleted. */ if (aIsSetter && (aValue != NULL) && !VALID_PTR(aValue)) - return E_INVALIDARG; + return setError(E_INVALIDARG, tr("Invalid value pointer")); /* aFlags can be null if it is to be left as is */ if (aIsSetter && (aFlags != NULL) && !VALID_PTR(aFlags)) - return E_INVALIDARG; + return setError(E_INVALIDARG, tr("Invalid flags pointer")); /* If this session is not in a VM process fend off the call. The caller * handles this correctly, by doing the operation in VBoxSVC. */ @@ -824,9 +948,17 @@ STDMETHODIMP Session::AccessGuestProperty(IN_BSTR aName, IN_BSTR aValue, IN_BSTR return mConsole->getGuestProperty(aName, aRetValue, aRetTimestamp, aRetFlags); else return mConsole->setGuestProperty(aName, aValue, aFlags); -#else /* VBOX_WITH_GUEST_PROPS not defined */ + +# else /* VBOX_COM_INPROC_API_CLIENT */ + /** @todo This is nonsense, non-VM API users shouldn't need to deal with this + * method call, VBoxSVC should be clever enough to see that the + * session doesn't have a console! */ + return E_ACCESSDENIED; +# endif /* VBOX_COM_INPROC_API_CLIENT */ + +#else /* VBOX_WITH_GUEST_PROPS */ ReturnComNotImplemented(); -#endif /* VBOX_WITH_GUEST_PROPS not defined */ +#endif /* VBOX_WITH_GUEST_PROPS */ } STDMETHODIMP Session::EnumerateGuestProperties(IN_BSTR aPatterns, @@ -835,7 +967,7 @@ STDMETHODIMP Session::EnumerateGuestProperties(IN_BSTR aPatterns, ComSafeArrayOut(LONG64, aTimestamps), ComSafeArrayOut(BSTR, aFlags)) { -#ifdef VBOX_WITH_GUEST_PROPS +#if defined(VBOX_WITH_GUEST_PROPS) && !defined(VBOX_COM_INPROC_API_CLIENT) AutoCaller autoCaller(this); AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); @@ -872,10 +1004,6 @@ STDMETHODIMP Session::EnumerateGuestProperties(IN_BSTR aPatterns, STDMETHODIMP Session::OnlineMergeMedium(IMediumAttachment *aMediumAttachment, ULONG aSourceIdx, ULONG aTargetIdx, - IMedium *aSource, IMedium *aTarget, - BOOL aMergeForward, - IMedium *aParentForTarget, - ComSafeArrayIn(IMedium *, aChildrenToReparent), IProgress *aProgress) { AutoCaller autoCaller(this); @@ -885,16 +1013,18 @@ STDMETHODIMP Session::OnlineMergeMedium(IMediumAttachment *aMediumAttachment, return setError(VBOX_E_INVALID_VM_STATE, tr("Machine is not locked by session (session state: %s)."), Global::stringifySessionState(mState)); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); CheckComArgNotNull(aMediumAttachment); - CheckComArgSafeArrayNotNull(aChildrenToReparent); - return mConsole->onlineMergeMedium(aMediumAttachment, aSourceIdx, - aTargetIdx, aSource, aTarget, - aMergeForward, aParentForTarget, - ComSafeArrayInArg(aChildrenToReparent), + return mConsole->onlineMergeMedium(aMediumAttachment, + aSourceIdx, aTargetIdx, aProgress); +#else + AssertFailed(); + return E_NOTIMPL; +#endif } STDMETHODIMP Session::EnableVMMStatistics(BOOL aEnable) @@ -905,11 +1035,70 @@ STDMETHODIMP Session::EnableVMMStatistics(BOOL aEnable) AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); mConsole->enableVMMStatistics(aEnable); return S_OK; +#else + AssertFailed(); + return E_NOTIMPL; +#endif +} + +STDMETHODIMP Session::PauseWithReason(Reason_T aReason) +{ + AutoCaller autoCaller(this); + AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); + + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); + AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); + AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT + AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); + + return mConsole->pause(aReason); +#else + AssertFailed(); + return E_NOTIMPL; +#endif +} + +STDMETHODIMP Session::ResumeWithReason(Reason_T aReason) +{ + AutoCaller autoCaller(this); + AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); + + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); + AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); + AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT + AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); + + return mConsole->resume(aReason); +#else + AssertFailed(); + return E_NOTIMPL; +#endif +} + +STDMETHODIMP Session::SaveStateWithReason(Reason_T aReason, IProgress **aProgress) +{ + AutoCaller autoCaller(this); + AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); + + AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); + AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); + AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); +#ifndef VBOX_COM_INPROC_API_CLIENT + AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); + + return mConsole->saveState(aReason, aProgress); +#else + AssertFailed(); + return E_NOTIMPL; +#endif } // private methods @@ -953,16 +1142,9 @@ HRESULT Session::unlockMachine(bool aFinalRelease, bool aFromServer) mState = SessionState_Unlocked; mType = SessionType_Null; -#if defined(RT_OS_WINDOWS) - Assert(!mIPCSem && !mIPCThreadSem); -#elif defined(RT_OS_OS2) - Assert(mIPCThread == NIL_RTTHREAD && - mIPCThreadSem == NIL_RTSEMEVENT); -#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) - Assert(mIPCSem == -1); -#else -# error "Port me!" -#endif + + Assert(!mClientTokenHolder); + LogFlowThisFuncLeave(); return S_OK; } @@ -972,11 +1154,15 @@ HRESULT Session::unlockMachine(bool aFinalRelease, bool aFromServer) if (mType == SessionType_WriteLock) { +#ifndef VBOX_COM_INPROC_API_CLIENT if (!mConsole.isNull()) { mConsole->uninit(); mConsole.setNull(); } +#else + mRemoteMachine.setNull(); +#endif } else { @@ -1032,7 +1218,12 @@ HRESULT Session::unlockMachine(bool aFinalRelease, bool aFromServer) if (mType == SessionType_WriteLock) { - releaseIPCSemaphore(); + if (mClientTokenHolder) + { + delete mClientTokenHolder; + mClientTokenHolder = NULL; + } + if (!aFinalRelease && !aFromServer) { /* @@ -1056,286 +1247,4 @@ HRESULT Session::unlockMachine(bool aFinalRelease, bool aFromServer) return S_OK; } -/** @note To be called only from #AssignMachine() */ -HRESULT Session::grabIPCSemaphore() -{ - HRESULT rc = E_FAIL; - - /* open the IPC semaphore based on the sessionId and try to grab it */ - Bstr ipcId; - rc = mControl->GetIPCId(ipcId.asOutParam()); - AssertComRCReturnRC(rc); - - LogFlowThisFunc(("ipcId='%ls'\n", ipcId.raw())); - -#if defined(RT_OS_WINDOWS) - - /* - * Since Session is an MTA object, this method can be executed on - * any thread, and this thread will not necessarily match the thread on - * which close() will be called later. Therefore, we need a separate - * thread to hold the IPC mutex and then release it in close(). - */ - - mIPCThreadSem = ::CreateEvent(NULL, FALSE, FALSE, NULL); - AssertMsgReturn(mIPCThreadSem, - ("Cannot create an event sem, err=%d", ::GetLastError()), - E_FAIL); - - void *data[3]; - data[0] = (void*)(BSTR)ipcId.raw(); - data[1] = (void*)mIPCThreadSem; - data[2] = 0; /* will get an output from the thread */ - - /* create a thread to hold the IPC mutex until signalled to release it */ - RTTHREAD tid; - int vrc = RTThreadCreate(&tid, IPCMutexHolderThread, (void*)data, 0, RTTHREADTYPE_MAIN_WORKER, 0, "IPCHolder"); - AssertRCReturn(vrc, E_FAIL); - - /* wait until thread init is completed */ - DWORD wrc = ::WaitForSingleObject(mIPCThreadSem, INFINITE); - AssertMsg(wrc == WAIT_OBJECT_0, ("Wait failed, err=%d\n", ::GetLastError())); - Assert(data[2]); - - if (wrc == WAIT_OBJECT_0 && data[2]) - { - /* memorize the event sem we should signal in close() */ - mIPCSem = (HANDLE)data[2]; - rc = S_OK; - } - else - { - ::CloseHandle(mIPCThreadSem); - mIPCThreadSem = NULL; - rc = E_FAIL; - } - -#elif defined(RT_OS_OS2) - - /* We use XPCOM where any message (including close()) can arrive on any - * worker thread (which will not necessarily match this thread that opens - * the mutex). Therefore, we need a separate thread to hold the IPC mutex - * and then release it in close(). */ - - int vrc = RTSemEventCreate(&mIPCThreadSem); - AssertRCReturn(vrc, E_FAIL); - - void *data[3]; - data[0] = (void*)ipcId.raw(); - data[1] = (void*)mIPCThreadSem; - data[2] = (void*)false; /* will get the thread result here */ - - /* create a thread to hold the IPC mutex until signalled to release it */ - vrc = RTThreadCreate(&mIPCThread, IPCMutexHolderThread, (void *) data, - 0, RTTHREADTYPE_MAIN_WORKER, 0, "IPCHolder"); - AssertRCReturn(vrc, E_FAIL); - - /* wait until thread init is completed */ - vrc = RTThreadUserWait (mIPCThread, RT_INDEFINITE_WAIT); - AssertReturn(RT_SUCCESS(vrc) || vrc == VERR_INTERRUPTED, E_FAIL); - - /* the thread must succeed */ - AssertReturn((bool)data[2], E_FAIL); - -#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) - -# ifdef VBOX_WITH_NEW_SYS_V_KEYGEN - Utf8Str ipcKey = ipcId; - key_t key = RTStrToUInt32(ipcKey.c_str()); - AssertMsgReturn (key != 0, - ("Key value of 0 is not valid for IPC semaphore"), - E_FAIL); -# else /* !VBOX_WITH_NEW_SYS_V_KEYGEN */ - Utf8Str semName = ipcId; - char *pszSemName = NULL; - RTStrUtf8ToCurrentCP (&pszSemName, semName); - key_t key = ::ftok (pszSemName, 'V'); - RTStrFree (pszSemName); -# endif /* !VBOX_WITH_NEW_SYS_V_KEYGEN */ - - mIPCSem = ::semget (key, 0, 0); - AssertMsgReturn (mIPCSem >= 0, - ("Cannot open IPC semaphore, errno=%d", errno), - E_FAIL); - - /* grab the semaphore */ - ::sembuf sop = { 0, -1, SEM_UNDO }; - int rv = ::semop (mIPCSem, &sop, 1); - AssertMsgReturn (rv == 0, - ("Cannot grab IPC semaphore, errno=%d", errno), - E_FAIL); - -#else -# error "Port me!" -#endif - - return rc; -} - -/** @note To be called only from #close() */ -void Session::releaseIPCSemaphore() -{ - /* release the IPC semaphore */ -#if defined(RT_OS_WINDOWS) - - if (mIPCSem && mIPCThreadSem) - { - /* - * tell the thread holding the IPC mutex to release it; - * it will close mIPCSem handle - */ - ::SetEvent (mIPCSem); - /* wait for the thread to finish */ - ::WaitForSingleObject (mIPCThreadSem, INFINITE); - ::CloseHandle (mIPCThreadSem); - - mIPCThreadSem = NULL; - mIPCSem = NULL; - } - -#elif defined(RT_OS_OS2) - - if (mIPCThread != NIL_RTTHREAD) - { - Assert (mIPCThreadSem != NIL_RTSEMEVENT); - - /* tell the thread holding the IPC mutex to release it */ - int vrc = RTSemEventSignal (mIPCThreadSem); - AssertRC(vrc == NO_ERROR); - - /* wait for the thread to finish */ - vrc = RTThreadUserWait (mIPCThread, RT_INDEFINITE_WAIT); - Assert (RT_SUCCESS(vrc) || vrc == VERR_INTERRUPTED); - - mIPCThread = NIL_RTTHREAD; - } - - if (mIPCThreadSem != NIL_RTSEMEVENT) - { - RTSemEventDestroy (mIPCThreadSem); - mIPCThreadSem = NIL_RTSEMEVENT; - } - -#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) - - if (mIPCSem >= 0) - { - ::sembuf sop = { 0, 1, SEM_UNDO }; - ::semop (mIPCSem, &sop, 1); - - mIPCSem = -1; - } - -#else -# error "Port me!" -#endif -} - -#if defined(RT_OS_WINDOWS) -/** VM IPC mutex holder thread */ -DECLCALLBACK(int) IPCMutexHolderThread (RTTHREAD Thread, void *pvUser) -{ - LogFlowFuncEnter(); - - Assert (pvUser); - void **data = (void **) pvUser; - - BSTR sessionId = (BSTR)data[0]; - HANDLE initDoneSem = (HANDLE)data[1]; - - HANDLE ipcMutex = ::OpenMutex (MUTEX_ALL_ACCESS, FALSE, sessionId); - AssertMsg (ipcMutex, ("cannot open IPC mutex, err=%d\n", ::GetLastError())); - - if (ipcMutex) - { - /* grab the mutex */ - DWORD wrc = ::WaitForSingleObject (ipcMutex, 0); - AssertMsg (wrc == WAIT_OBJECT_0, ("cannot grab IPC mutex, err=%d\n", wrc)); - if (wrc == WAIT_OBJECT_0) - { - HANDLE finishSem = ::CreateEvent (NULL, FALSE, FALSE, NULL); - AssertMsg (finishSem, ("cannot create event sem, err=%d\n", ::GetLastError())); - if (finishSem) - { - data[2] = (void*)finishSem; - /* signal we're done with init */ - ::SetEvent (initDoneSem); - /* wait until we're signaled to release the IPC mutex */ - ::WaitForSingleObject (finishSem, INFINITE); - /* release the IPC mutex */ - LogFlow (("IPCMutexHolderThread(): releasing IPC mutex...\n")); - BOOL success = ::ReleaseMutex (ipcMutex); - AssertMsg (success, ("cannot release mutex, err=%d\n", ::GetLastError())); - ::CloseHandle (ipcMutex); - ::CloseHandle (finishSem); - } - } - } - - /* signal we're done */ - ::SetEvent (initDoneSem); - - LogFlowFuncLeave(); - - return 0; -} -#endif - -#if defined(RT_OS_OS2) -/** VM IPC mutex holder thread */ -DECLCALLBACK(int) IPCMutexHolderThread (RTTHREAD Thread, void *pvUser) -{ - LogFlowFuncEnter(); - - Assert (pvUser); - void **data = (void **) pvUser; - - Utf8Str ipcId = (BSTR)data[0]; - RTSEMEVENT finishSem = (RTSEMEVENT)data[1]; - - LogFlowFunc (("ipcId='%s', finishSem=%p\n", ipcId.raw(), finishSem)); - - HMTX ipcMutex = NULLHANDLE; - APIRET arc = ::DosOpenMutexSem ((PSZ) ipcId.raw(), &ipcMutex); - AssertMsg (arc == NO_ERROR, ("cannot open IPC mutex, arc=%ld\n", arc)); - - if (arc == NO_ERROR) - { - /* grab the mutex */ - LogFlowFunc (("grabbing IPC mutex...\n")); - arc = ::DosRequestMutexSem (ipcMutex, SEM_IMMEDIATE_RETURN); - AssertMsg (arc == NO_ERROR, ("cannot grab IPC mutex, arc=%ld\n", arc)); - if (arc == NO_ERROR) - { - /* store the answer */ - data[2] = (void*)true; - /* signal we're done */ - int vrc = RTThreadUserSignal (Thread); - AssertRC(vrc); - - /* wait until we're signaled to release the IPC mutex */ - LogFlowFunc (("waiting for termination signal..\n")); - vrc = RTSemEventWait (finishSem, RT_INDEFINITE_WAIT); - Assert (arc == ERROR_INTERRUPT || ERROR_TIMEOUT); - - /* release the IPC mutex */ - LogFlowFunc (("releasing IPC mutex...\n")); - arc = ::DosReleaseMutexSem (ipcMutex); - AssertMsg (arc == NO_ERROR, ("cannot release mutex, arc=%ld\n", arc)); - } - - ::DosCloseMutexSem (ipcMutex); - } - - /* store the answer */ - data[1] = (void*)false; - /* signal we're done */ - int vrc = RTThreadUserSignal (Thread); - AssertRC(vrc); - - LogFlowFuncLeave(); - - return 0; -} -#endif /* vi: set tabstop=4 shiftwidth=4 expandtab: */ |