GuestSessionImpl.cpp revision 4171ffb38eb8720b2ae9a8d13e95103ab26cfd12
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VirtualBox Main - Guest session handling.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copyright (C) 2012-2013 Oracle Corporation
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Base class representing an internal
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * asynchronous session task.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync virtual ~GuestSessionTaskInternal(void) { }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const ComObjPtr<GuestSession> &Session(void) const { return mSession; }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Class for asynchronously opening a guest session.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncclass GuestSessionTaskInternalOpen : public GuestSessionTaskInternal
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestSessionTaskInternalOpen(GuestSession *pSession)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Internal listener class to serve events in an
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * active manner, e.g. without polling delays.
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc2 = mSession->signalWaitEvent(aType, aEvent);
726fc44ad0bd65a178ad4c3ab46ebd6cd3208e99vboxsync LogFlowFunc(("Signalling events of type=%ld, session=%p resulted in rc=%Rrc\n",
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsynctypedef ListenerImpl<GuestSessionListener, GuestSession*> GuestSessionListenerImpl;
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync// constructor / destructor
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync/////////////////////////////////////////////////////////////////////////////
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync// public initializer/uninitializer for internal purposes only
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync/////////////////////////////////////////////////////////////////////////////
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync * Initializes a guest session but does *not* open in on the guest side
726fc44ad0bd65a178ad4c3ab46ebd6cd3208e99vboxsync * yet. This needs to be done via the openSession() / openSessionAsync calls.
26824086a3f6b36cd911058f1d9b4c0b944706fbvboxsync * @return IPRT status code.
26824086a3f6b36cd911058f1d9b4c0b944706fbvboxsync ** @todo Docs!
68ef804c4ec232c58e2c03c8fc6afe3765c5c0d1vboxsyncint GuestSession::init(Guest *pGuest, const GuestSessionStartupInfo &ssInfo,
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync LogFlowThisFunc(("pGuest=%p, ssInfo=%p, guestCreds=%p\n",
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync /* Enclose the state transition NotReady->InInit->Ready. */
26824086a3f6b36cd911058f1d9b4c0b944706fbvboxsync AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Copy over startup info. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Use an overloaded copy operator. Later. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mSession.mOpenTimeoutMS = ssInfo.mOpenTimeoutMS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Use an overloaded copy operator. Later. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mCredentials.mPassword = guestCreds.mPassword;
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync hr = mEventSource->init(static_cast<IGuestSession*>(this));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestSessionListener *pListener = new GuestSessionListener();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Confirm a successful initialization when it's the case. */
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync LogFlowThisFunc(("mName=%s, mID=%RU32, mIsInternal=%RTbool, rc=%Rrc\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mSession.mName.c_str(), mData.mSession.mID, mData.mSession.mIsInternal, rc));
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync * Uninitializes the instance.
6b022885f2cb6a55167609edecd89570cd80001dvboxsync * Called from FinalRelease().
6b022885f2cb6a55167609edecd89570cd80001dvboxsync /* Enclose the state transition Ready->InUninit->NotReady. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("Closing directories (%RU64 total)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (SessionDirectories::iterator itDirs = mData.mDirectories.begin();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (SessionFiles::iterator itFiles = mData.mFiles.begin();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("Closing processes (%RU64 total)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (SessionProcesses::iterator itProcs = mData.mProcesses.begin();
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsync LogFlowThisFunc(("mNumObjects=%RU32\n", mData.mNumObjects));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// implementation of public getters/setters for attributes
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync/////////////////////////////////////////////////////////////////////////////
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::COMGETTER(User)(BSTR *aUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::COMGETTER(Domain)(BSTR *aDomain)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::COMGETTER(Name)(BSTR *aName)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
0e77737b0ba913683e614db11463b31ca67aacbevboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsyncSTDMETHODIMP GuestSession::COMGETTER(Id)(ULONG *aId)
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsyncSTDMETHODIMP GuestSession::COMGETTER(Status)(GuestSessionStatus_T *aStatus)
86b687e7808a36be33c43ae58adc8ab22d378feavboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::COMGETTER(Timeout)(ULONG *aTimeout)
6b022885f2cb6a55167609edecd89570cd80001dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::COMSETTER(Timeout)(ULONG aTimeout)
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
6b022885f2cb6a55167609edecd89570cd80001dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsyncSTDMETHODIMP GuestSession::COMGETTER(ProtocolVersion)(ULONG *aVersion)
6b022885f2cb6a55167609edecd89570cd80001dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsyncSTDMETHODIMP GuestSession::COMGETTER(Environment)(ComSafeArrayOut(BSTR, aEnvironment))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync environment.detachTo(ComSafeArrayOutArg(aEnvironment));
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsyncSTDMETHODIMP GuestSession::COMSETTER(Environment)(ComSafeArrayIn(IN_BSTR, aValues))
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aValues));
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync if (!strEnv.isEmpty()) /* Silently skip empty entries. */
6b022885f2cb6a55167609edecd89570cd80001dvboxsync HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncSTDMETHODIMP GuestSession::COMGETTER(Processes)(ComSafeArrayOut(IGuestProcess *, aProcesses))
03319aeaef07ef63a404237f2cb56199131f4a03vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync SafeIfaceArray<IGuestProcess> collection(mData.mProcesses);
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync collection.detachTo(ComSafeArrayOutArg(aProcesses));
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync LogFlowFunc(("mProcesses=%zu\n", collection.size()));
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncSTDMETHODIMP GuestSession::COMGETTER(Directories)(ComSafeArrayOut(IGuestDirectory *, aDirectories))
6b022885f2cb6a55167609edecd89570cd80001dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync SafeIfaceArray<IGuestDirectory> collection(mData.mDirectories);
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync collection.detachTo(ComSafeArrayOutArg(aDirectories));
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync LogFlowFunc(("mDirectories=%zu\n", collection.size()));
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsyncSTDMETHODIMP GuestSession::COMGETTER(Files)(ComSafeArrayOut(IGuestFile *, aFiles))
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync SafeIfaceArray<IGuestFile> collection(mData.mFiles);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
6b022885f2cb6a55167609edecd89570cd80001dvboxsyncSTDMETHODIMP GuestSession::COMGETTER(EventSource)(IEventSource ** aEventSource)
8e8844a522f5d335f177a0313b03067d79cce201vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync // no need to lock - lifetime constant
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync// private methods
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync///////////////////////////////////////////////////////////////////////////////
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncint GuestSession::closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc)
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync LogFlowThisFunc(("uFlags=%x, uTimeoutMS=%RU32\n", uFlags, uTimeoutMS));
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync /* Guest Additions < 4.3 don't support closing dedicated
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync guest sessions, skip. */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync LogFlowThisFunc(("Installed Guest Additions don't support closing dedicated sessions, skipping\n"));
8e8844a522f5d335f177a0313b03067d79cce201vboxsync /** @todo uFlags validation. */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync LogFlowThisFunc(("Session ID=%RU32 not started (anymore), status now is: %ld\n",
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync LogFlowThisFunc(("Sending closing request to guest session ID=%RU32, uFlags=%x\n",
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync alock.release(); /* Drop the write lock before waiting. */
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync vrc = waitForStatusChange(pEvent, GuestSessionWaitForFlag_Terminate, uTimeoutMS,
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsyncint GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode,
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync /* Construct arguments. */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncinline bool GuestSession::directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionDirectories::const_iterator it = mData.mDirectories.find(uDirID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::directoryRemoveFromList(GuestDirectory *pDirectory)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (SessionDirectories::iterator itDirs = mData.mDirectories.begin();
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync HRESULT hr = itDirs->second->COMGETTER(DirectoryName)(strName.asOutParam());
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync LogFlowFunc(("Removing directory \"%s\" (Session: %RU32) (now total %ld directories)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Utf8Str(strName).c_str(), mData.mSession.mID, mData.mDirectories.size() - 1));
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncint GuestSession::directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFlags,
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync AssertReturn(!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
08bc90fc2848c80bf8270bedc883745b8398e186vboxsync LogFlowThisFunc(("strPath=%s, uFlags=0x%x\n", strPath.c_str(), uFlags));
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync int vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync /* Prepare HGCM call. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync alock.release(); /* Drop write lock before sending. */
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsyncint GuestSession::objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath,
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync bool fDirectory, const Utf8Str &strName, int *pGuestRc)
51d4024e2984de499ecd878341898f71f55cf9e0vboxsync LogFlowThisFunc(("strTemplate=%s, strPath=%s, fDirectory=%RTbool, strName=%s\n",
8b984478b755f4d3091b977d9beac9fb7434279fvboxsync strTemplate.c_str(), strPath.c_str(), fDirectory, strName.c_str()));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKTEMP);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (strPath.length()) /* Otherwise use /tmp or equivalent. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::directoryOpenInternal(const GuestDirectoryOpenInfo &openInfo,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync openInfo.mPath.c_str(), openInfo.mFilter.c_str(), openInfo.mFlags));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS)
47b5427d1a541bcd269bc625c35b19d849071edfvboxsync /* Create a new (host-based) directory ID and assign it. */
f02b41a7e54fc4e6b714f4e60260d94614d6e2e7vboxsync /* Is the directory ID already used? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!directoryExists(uNewDirID, NULL /* pDirectory */))
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync /* Callback with context ID was not found. This means
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * we can use this context ID for our new callback we want
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * to add below. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break; /* Don't try too hard. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Create the directory object. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = pDirectory->init(pConsole, this /* Parent */,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Since this is a synchronous guest call we have to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * register the file object first, releasing the session's
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * lock and then proceed with the actual opening command
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * -- otherwise the file's opening callback would hang
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * because the session's lock still is in place.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Add the created directory to our map. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("Added new guest directory \"%s\" (Session: %RU32) (now total %ld dirs, %ld objects)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync openInfo.mPath.c_str(), mData.mSession.mID, mData.mFiles.size(), mData.mNumObjects));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync alock.release(); /* Release lock before firing off event. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Fire off a VBoxEventType_OnGuestDirectoryRegistered event? */
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync /* Nothing further to do here yet. */
eb90d5a431eee79842fb6c676c05aa9ca51ca6a9vboxsyncint GuestSession::dispatchToDirectory(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t uDirID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComObjPtr<GuestDirectory> pDirectory(itDir->second);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = pDirectory->callbackDispatcher(pCtxCb, pSvcCb);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::dispatchToFile(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t uFileID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t uObjectID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Since we don't know which type the object is, we need to through all
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * all objects. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Speed this up by adding an object type to the callback context! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionProcesses::const_iterator itProc = mData.mProcesses.find(uObjectID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionFiles::const_iterator itFile = mData.mFiles.find(uObjectID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionDirectories::const_iterator itDir = mData.mDirectories.find(uObjectID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t uProcessID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Set protocol version so that pSvcCb can
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * be interpreted right. */
5b6e2c9a765c3c72295acc15791af8a700746956vboxsyncint GuestSession::dispatchToThis(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("sessionID=%RU32, CID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mSession.mID, pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync /** @todo Handle closing all guest objects. */
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync case GUEST_SESSION_NOTIFY: /* Guest Additions >= 4.3.0. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Silently skip unknown callbacks. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncinline bool GuestSession::fileExists(uint32_t uFileID, ComObjPtr<GuestFile> *pFile)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionFiles::const_iterator it = mData.mFiles.find(uFileID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::fileRemoveFromList(GuestFile *pFile)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (SessionFiles::iterator itFiles = mData.mFiles.begin();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Make sure to consume the pointer before the one of thfe
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * iterator gets released. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HRESULT hr = pCurFile->COMGETTER(FileName)(strName.asOutParam());
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("Removing guest file \"%s\" (Session: %RU32) (now total %ld files, %ld objects)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Utf8Str(strName).c_str(), mData.mSession.mID, mData.mFiles.size() - 1, mData.mNumObjects - 1));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync alock.release(); /* Release lock before firing off event. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fireGuestFileRegisteredEvent(mEventSource, this, pCurFile,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync false /* Unregistered */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo,
8b03ab0bcd5c238021bc8a43d887dd9d0870c0f5vboxsync LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, uOffset=%RU64\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync openInfo.mFileName.c_str(), openInfo.mOpenMode.c_str(), openInfo.mDisposition.c_str(),
8b03ab0bcd5c238021bc8a43d887dd9d0870c0f5vboxsync /* Guest Additions < 4.3 don't support handling
8b03ab0bcd5c238021bc8a43d887dd9d0870c0f5vboxsync guest files, skip. */
8b03ab0bcd5c238021bc8a43d887dd9d0870c0f5vboxsync LogFlowThisFunc(("Installed Guest Additions don't support handling guest files, skipping\n"));
8b03ab0bcd5c238021bc8a43d887dd9d0870c0f5vboxsync if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Create a new (host-based) file ID and assign it. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Is the file ID already used? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Callback with context ID was not found. This means
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * we can use this context ID for our new callback we want
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * to add below. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break; /* Don't try too hard. */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /* Create the directory object. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = pFile->init(pConsole, this /* GuestSession */,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Since this is a synchronous guest call we have to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * register the file object first, releasing the session's
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * lock and then proceed with the actual opening command
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * -- otherwise the file's opening callback would hang
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * because the session's lock still is in place.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Add the created file to our vector. */
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync LogFlowFunc(("Added new guest file \"%s\" (Session: %RU32) (now total %ld files, %ld objects)\n",
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync openInfo.mFileName.c_str(), mData.mSession.mID, mData.mFiles.size(), mData.mNumObjects));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync alock.release(); /* Release lock before firing off event. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fireGuestFileRegisteredEvent(mEventSource, this, pFile,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync true /* Registered */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = pFile->openFile(30 * 1000 /* 30s timeout */, &guestRc);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsyncint GuestSession::fileQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsyncint GuestSession::fileQuerySizeInternal(const Utf8Str &strPath, int64_t *pllSize, int *pGuestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = fileQueryInfoInternal(strPath, objData, pGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::fsQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Merge this with IGuestFile::queryInfo(). */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_STAT);
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync /* Construct arguments. */
6b022885f2cb6a55167609edecd89570cd80001dvboxsync procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncconst GuestCredentials& GuestSession::getCredentials(void)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncconst GuestEnvironment& GuestSession::getEnvironment(void)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* static */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncUtf8Str GuestSession::guestErrorToString(int guestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("VMM device is not available (is the VM running?)"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("The guest execution service is not available"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("The specified user was not able to logon on guest"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("The guest did not respond within time"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("The session operation was canceled"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("Invalid user/password credentials"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("Maximum number of concurrent guest processes has been reached"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case VERR_NOT_EQUAL: /** @todo Imprecise to the user; can mean anything and all. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("Unable to retrieve requested information"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strError += Utf8StrFmt(tr("The guest execution service is not ready (yet)"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Checks if this session is ready state where it can handle
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * all session-bound actions (like guest processes, guest files).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Only used by official API methods. Will set an external
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * error when not ready.
c33db29e7b41467a35675031f5f5233839909083vboxsync /** @todo Be a bit more informative. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_UNEXPECTED, tr("Session is not in started state"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** No locking! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::onSessionStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* pCallback is optional. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* pSvcCb->mpaParms[0] always contains the context ID. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = pSvcCbData->mpaParms[1].getUInt32(&dataCb.uType);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = pSvcCbData->mpaParms[2].getUInt32(&dataCb.uResult);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("ID=%RU32, uType=%RU32, guestRc=%Rrc\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mSession.mID, dataCb.uType, dataCb.uResult));
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync GuestSessionStatus_T sessionStatus = GuestSessionStatus_Undefined;
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync int guestRc = dataCb.uResult; /** @todo uint32_t vs. int. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync sessionStatus = GuestSessionStatus_TimedOutAbnormally;
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync /* Set the session status. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("ID=%RU32, guestRc=%Rrc\n", mData.mSession.mID, guestRc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::startSessionInternal(int *pGuestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("mID=%RU32, mName=%s, uProtocolVersion=%RU32, openFlags=%x, openTimeoutMS=%RU32\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mSession.mID, mData.mSession.mName.c_str(), mData.mProtocolVersion,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mSession.mOpenFlags, mData.mSession.mOpenTimeoutMS));
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync /* Guest Additions < 4.3 don't support opening dedicated
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync guest sessions. Simply return success here. */
75fca099c974cbbd48f132af1378c60232614760vboxsync LogFlowThisFunc(("Installed Guest Additions don't support opening dedicated sessions, skipping\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo mData.mSession.uFlags validation. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Set current session status. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mRC = VINF_SUCCESS; /* Clear previous error, if any. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
a27fbcbb29ffc2196c2ebd0f2dad92f40c7ec65dvboxsync paParms[i++].setPointer((void*)mData.mCredentials.mUser.c_str(),
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync paParms[i++].setPointer((void*)mData.mCredentials.mPassword.c_str(),
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync paParms[i++].setPointer((void*)mData.mCredentials.mDomain.c_str(),
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync alock.release(); /* Drop write lock before sending. */
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync vrc = sendCommand(HOST_SESSION_CREATE, i, paParms);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = waitForStatusChange(pEvent, GuestSessionWaitForFlag_Start,
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * Unable to start guest session - update its current state.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * Since there is no (official API) way to recover a failed guest session
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * this also marks the end state. Internally just calling this
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync * same function again will work though.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Asynchronously open the session on the guest by kicking off a
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * worker thread. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync std::auto_ptr<GuestSessionTaskInternalOpen> pTask(new GuestSessionTaskInternalOpen(this));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = RTThreadCreate(NULL, GuestSession::startSessionThread,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "gctlSesStart");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* pTask is now owned by openSessionThread(), so release it. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* static */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLCALLBACK(int) GuestSession::startSessionThread(RTTHREAD Thread, void *pvUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync std::auto_ptr<GuestSessionTaskInternalOpen> pTask(static_cast<GuestSessionTaskInternalOpen*>(pvUser));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const ComObjPtr<GuestSession> pSession(pTask->Session());
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = pSession->startSessionInternal(NULL /* Guest rc, ignored */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Nothing to do here anymore. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::pathRenameInternal(const Utf8Str &strSource, const Utf8Str &strDest,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(!(uFlags & ~PATHRENAME_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("strSource=%s, strDest=%s, uFlags=0x%x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
315f443a509c31db47b8f5cb94d26e54c3d5c497vboxsync /* Prepare HGCM call. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync alock.release(); /* Drop write lock before sending. */
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsyncint GuestSession::processRemoveFromList(GuestProcess *pProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("Closing process (PID=%RU32) ...\n", uPID));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionProcesses::iterator itProcs = mData.mProcesses.begin();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Make sure to consume the pointer before the one of thfe
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * iterator gets released. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("Removing process ID=%RU32 (Session: %RU32), guest PID=%RU32 (now total %ld processes, %ld objects)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pProcess->getObjectID(), mData.mSession.mID, uPID, mData.mProcesses.size() - 1, mData.mNumObjects - 1));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync alock.release(); /* Release lock before firing off event. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fireGuestProcessRegisteredEvent(mEventSource, this /* Session */, pCurProcess,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Creates but does *not* start the process yet. See GuestProcess::startProcess() or
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * GuestProcess::startProcessAsync() for that.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return IPRT status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param procInfo
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pProcess
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::processCreateExInteral(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("mCmd=%s, mFlags=%x, mTimeoutMS=%RU32\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mCommand.c_str(), procInfo.mFlags, procInfo.mTimeoutMS));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ProcessArguments::const_iterator it = procInfo.mArguments.begin();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Validate flags. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( !(procInfo.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && !(procInfo.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && !(procInfo.mFlags & ProcessCreateFlag_NoProfile)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && !(procInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && !(procInfo.mFlags & ProcessCreateFlag_WaitForStdErr))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( (procInfo.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && ( (procInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || (procInfo.mFlags & ProcessCreateFlag_WaitForStdErr)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Adjust timeout. If set to 0, we define
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * an infinite timeout. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @tood Implement process priority + affinity. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Create a new (host-based) process ID and assign it. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Is the context ID already used? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!processExists(uNewProcessID, NULL /* pProcess */))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Callback with context ID was not found. This means
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * we can use this context ID for our new callback we want
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * to add below. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break; /* Don't try too hard. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Create the process object. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = pProcess->init(mParent->getConsole() /* Console */, this /* Session */,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Add the created process to our map. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32 (now total %ld processes, %ld objects)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mData.mSession.mID, uNewProcessID, mData.mProcesses.size(), mData.mNumObjects));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fireGuestProcessRegisteredEvent(mEventSource, this /* Session */, pProcess,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncinline bool GuestSession::processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionProcesses::const_iterator it = mData.mProcesses.find(uProcessID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncinline int GuestSession::processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* pProcess is optional. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionProcesses::iterator itProcs = mData.mProcesses.begin();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (; itProcs != mData.mProcesses.end(); itProcs++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComObjPtr<GuestProcess> pCurProc = itProcs->second;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComObjPtr<Console> pConsole = mParent->getConsole();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Forward the information to the VMM device. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("uFunction=%RU32, uParms=%RU32\n", uFunction, uParms));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = pVMMDev->hgcmHostCall(HGCMSERVICE_NAME, uFunction, uParms, paParms);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo What to do here? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Not needed within testcases. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* static */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT GuestSession::setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pInterface->setError(VBOX_E_IPRT_ERROR, GuestSession::guestErrorToString(guestRc).c_str());
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Does not do locking; caller is responsible for that! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::setSessionStatus(GuestSessionStatus_T sessionStatus, int sessionRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("oldStatus=%ld, newStatus=%ld, sessionRc=%Rrc\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg(RT_FAILURE(sessionRc), ("Guest rc must be an error (%Rrc)\n", sessionRc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Do not allow overwriting an already set error. If this happens
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync * this means we forgot some error checking/locking somewhere. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg(RT_SUCCESS(mData.mRC), ("Guest rc already set (to %Rrc)\n", mData.mRC));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg(RT_SUCCESS(sessionRc), ("Guest rc must not be an error (%Rrc)\n", sessionRc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc2 = errorInfo->initEx(VBOX_E_IPRT_ERROR, sessionRc,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fireGuestSessionStateChangedEvent(mEventSource, this,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::signalWaiters(GuestSessionWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS */)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*LogFlowThisFunc(("enmWaitResult=%d, rc=%Rrc, mWaitCount=%RU32, mWaitEvent=%p\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync enmWaitResult, rc, mData.mWaitCount, mData.mWaitEvent));*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Note: No write locking here -- already done in the caller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*if (mData.mWaitEvent)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = mData.mWaitEvent->Signal(enmWaitResult, rc);*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::startTaskAsync(const Utf8Str &strTaskDesc,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestSessionTask *pTask, ComObjPtr<Progress> &pProgress)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("strTaskDesc=%s, pTask=%p\n", strTaskDesc.c_str(), pTask));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Create the progress object. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = pProgress->init(static_cast<IGuestSession*>(this),
9c425bdea5f0991df62922b1584b805a86f2f898vboxsync /* Initialize our worker task. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Don't destruct on success. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Queries/collects information prior to establishing a guest session.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This is necessary to know which guest control protocol version to use,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * among other things (later).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @return IPRT status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Try querying the guest control protocol version running on the guest.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This is done using the Guest Additions version
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t uVerAdditions = pGuest->getAdditionsVersion();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t uVBoxMajor = VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t uVBoxMinor = VBOX_FULL_VERSION_GET_MINOR(uVerAdditions);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Hardcode the to-used protocol version; nice for testing side effects. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* VBox 5.0 and up. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* VBox 4.3 and up. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Build revision is ignored. */
18db01bbe01d709ed64ef78717e98b94b7fee056vboxsync LogFlowThisFunc(("uVerAdditions=%RU32 (%RU32.%RU32), mProtocolVersion=%RU32\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uVerAdditions, uVBoxMajor, uVBoxMinor, mData.mProtocolVersion));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Tell the user but don't bitch too often. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync static short s_gctrlLegacyWarning = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && s_gctrlLegacyWarning++ < 3) /** @todo Find a bit nicer text. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogRel((tr("Warning: Guest Additions are older (%ld.%ld) than host capabilities for guest control, please upgrade them. Using protocol version %ld now\n"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestSessionWaitResult_T &waitResult, int *pGuestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, mStatus=%RU32, mWaitCount=%RU32, mWaitEvent=%p, pGuestRc=%p\n",
6b022885f2cb6a55167609edecd89570cd80001dvboxsync fWaitFlags, uTimeoutMS, mData.mStatus, mData.mWaitCount, mData.mWaitEvent, pGuestRc));*/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Did some error occur before? Then skip waiting and return. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg(RT_FAILURE(mData.mRC), ("No error rc (%Rrc) set when guest session indicated an error\n", mData.mRC));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *pGuestRc = mData.mRC; /* Return last set error. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Guest Additions < 4.3 don't support session handling, skip. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync waitResult = GuestSessionWaitResult_WaitFlagNotSupported;
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync LogFlowThisFunc(("Installed Guest Additions don't support waiting for dedicated sessions, skipping\n"));
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync if (fWaitFlags & GuestSessionWaitForFlag_Terminate)
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync /* Handled above. */
06de36c1229f14000638fa27993b13c9133e85f5vboxsync /* Do the waiting below. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Unhandled session status %ld\n", mData.mStatus));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else if (fWaitFlags & GuestSessionWaitForFlag_Start)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Do the waiting below. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Unhandled session status %ld\n", mData.mStatus));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("sessionStatus=%ld, sessionRc=%Rrc, waitResult=%ld\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* No waiting needed? Return immediately using the last set error. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *pGuestRc = mData.mRC; /* Return last set error (if any). */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return RT_SUCCESS(mData.mRC) ? VINF_SUCCESS : VERR_GSTCTL_GUEST_ERROR;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync alock.release(); /* Release lock before waiting. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint GuestSession::waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GuestSessionStatus_T *pSessionStatus, int *pGuestRc)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(evtType == VBoxEventType_OnGuestSessionStateChanged);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComPtr<IGuestSessionStateChangedEvent> pChangedEvent = pIEvent;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HRESULT hr = pChangedEvent->COMGETTER(Error)(errorInfo.asOutParam());
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("Status changed event for session ID=%RU32, new status is: %ld (%Rrc)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RT_SUCCESS((int)lGuestRc) ? VINF_SUCCESS : (int)lGuestRc));
6b022885f2cb6a55167609edecd89570cd80001dvboxsync// implementation of public methods
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/////////////////////////////////////////////////////////////////////////////
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsync /* Close session on guest. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = closeSession(0 /* Flags */, 30 * 1000 /* Timeout */,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* On failure don't return here, instead do all the cleanup
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * work first and then return an error. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Remove ourselves from the session list. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc2 == VERR_NOT_FOUND) /* Not finding the session anymore isn't critical. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return GuestSession::setErrorExternal(this, guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::CopyFrom(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No source specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No destination specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionTaskCopyFrom *pTask = new SessionTaskCopyFrom(this /* GuestSession */,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from guest to \"%ls\" on the host"), aSource, aDest),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Return progress to the caller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Starting task for copying file \"%ls\" from guest to \"%ls\" on the host failed: %Rrc"), rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::CopyTo(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No source specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
19b725c530eb49600728765de7ed451cbe290740vboxsync return setError(E_INVALIDARG, tr("No destination specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SessionTaskCopyTo *pTask = new SessionTaskCopyTo(this /* GuestSession */,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from host to \"%ls\" on the guest"), aSource, aDest),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Return progress to the caller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Starting task for copying file \"%ls\" from host to \"%ls\" on the guest failed: %Rrc"), rc);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
75fca099c974cbbd48f132af1378c60232614760vboxsyncSTDMETHODIMP GuestSession::DirectoryCreate(IN_BSTR aPath, ULONG aMode,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No directory to create specified"));
19b725c530eb49600728765de7ed451cbe290740vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync com::SafeArray<DirectoryCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), fFlags);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComObjPtr <GuestDirectory> pDirectory; int guestRc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = directoryCreateInternal(Utf8Str(aPath), (uint32_t)aMode, fFlags, &guestRc);
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Invalid parameters given"));
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Unexpectedly aborted"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Could not create directory"));
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: %Rrc"), rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::DirectoryCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, BSTR *aDirectory)
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync if (RT_UNLIKELY((aTemplate) == NULL || *(aTemplate) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No template specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No directory name specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync int rc = objectCreateTempInternal(Utf8Str(aTemplate),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
9c425bdea5f0991df62922b1584b805a86f2f898vboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Temporary directory creation \"%s\" with template \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Utf8Str(aPath).c_str(), Utf8Str(aTemplate).c_str(), rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::DirectoryExists(IN_BSTR aPath, BOOL *aExists)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No directory to check existence for specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory existence \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
8c9d2065ca6efecd5661174e382314868c0d4b94vboxsyncSTDMETHODIMP GuestSession::DirectoryOpen(IN_BSTR aPath, IN_BSTR aFilter, ComSafeArrayIn(DirectoryOpenFlag_T, aFlags), IGuestDirectory **aDirectory)
8c9d2065ca6efecd5661174e382314868c0d4b94vboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
8c9d2065ca6efecd5661174e382314868c0d4b94vboxsync return setError(E_INVALIDARG, tr("No directory to open specified"));
8c9d2065ca6efecd5661174e382314868c0d4b94vboxsync if (RT_UNLIKELY((aFilter) != NULL && *(aFilter) != '\0'))
8c9d2065ca6efecd5661174e382314868c0d4b94vboxsync return setError(E_INVALIDARG, tr("Directory filters are not implemented yet"));
8c9d2065ca6efecd5661174e382314868c0d4b94vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
8c9d2065ca6efecd5661174e382314868c0d4b94vboxsync com::SafeArray<DirectoryOpenFlag_T> flags(ComSafeArrayInArg(aFlags));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("Open flags (%#x) not implemented yet"), fFlags);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComObjPtr <GuestDirectory> pDirectory; int guestRc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = directoryOpenInternal(openInfo, pDirectory, &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Return directory object to the caller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed; invalid parameters given",
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync hr = GuestDirectory::setErrorExternal(this, guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsyncSTDMETHODIMP GuestSession::DirectoryQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No directory to query information for specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Element \"%s\" exists but is not a directory",
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory information for \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::DirectoryRemove(IN_BSTR aPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No directory to remove specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* No flags; only remove the directory when empty. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = directoryRemoveInternal(Utf8Str(aPath), uFlags, &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Handling removing guest directories not supported by installed Guest Additions"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = GuestDirectory::setErrorExternal(this, guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Removing guest directory \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::DirectoryRemoveRecursive(IN_BSTR aPath, ComSafeArrayIn(DirectoryRemoveRecFlag_T, aFlags), IProgress **aProgress)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No directory to remove recursively specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = pProgress->init(static_cast<IGuestSession *>(this),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Note: At the moment we don't supply progress information while
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * deleting a guest directory recursively. So just complete
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the progress object right now. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Implement progress reporting on guest directory deletion! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Remove the directory + all its contents. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = directoryRemoveInternal(Utf8Str(aPath), uFlags, &guestRc);
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsync tr("Handling removing guest directories recursively not supported by installed Guest Additions"));
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Recursively removing guest directory \"%s\" failed: %Rrc"),
6b022885f2cb6a55167609edecd89570cd80001dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::DirectoryRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
75fca099c974cbbd48f132af1378c60232614760vboxsync if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync return setError(E_INVALIDARG, tr("No source directory to rename specified"));
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No destination directory to rename the source to specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* No flags; only remove the directory when empty. */
75fca099c974cbbd48f132af1378c60232614760vboxsync int vrc = pathRenameInternal(Utf8Str(aSource), Utf8Str(aDest), uFlags, &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Handling renaming guest directories not supported by installed Guest Additions"));
4cad44a5f7cfa7db8d5fb255a1df3b3cd1687853vboxsync tr("Renaming guest directory failed: %Rrc"), guestRc);
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Renaming guest directory \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsyncSTDMETHODIMP GuestSession::DirectorySetACL(IN_BSTR aPath, IN_BSTR aACL)
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::EnvironmentGet(IN_BSTR aName, BSTR *aValue)
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
54fe68d807196dc565de24055996e634ee40ee92vboxsync return setError(E_INVALIDARG, tr("No value name specified"));
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync Bstr strValue(mData.mEnvironment.Get(Utf8Str(aName)));
5be6801527b2bb09f4b481e28d771f366961cdacvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::EnvironmentSet(IN_BSTR aName, IN_BSTR aValue)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No value name specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = mData.mEnvironment.Set(Utf8Str(aName), Utf8Str(aValue));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::EnvironmentUnset(IN_BSTR aName)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::FileCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, IGuestFile **aFile)
6b022885f2cb6a55167609edecd89570cd80001dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::FileExists(IN_BSTR aPath, BOOL *aExists)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No file to check existence for specified"));
6b022885f2cb6a55167609edecd89570cd80001dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
6b022885f2cb6a55167609edecd89570cd80001dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information for \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::FileRemove(IN_BSTR aPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No file to remove specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync int vrc = fileRemoveInternal(Utf8Str(aPath), &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Removing file \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::FileOpen(IN_BSTR aPath, IN_BSTR aOpenMode, IN_BSTR aDisposition, ULONG aCreationMode, IGuestFile **aFile)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Bstr strSharingMode = ""; /* Sharing mode is ignored. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return FileOpenEx(aPath, aOpenMode, aDisposition, strSharingMode.raw(), aCreationMode,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::FileOpenEx(IN_BSTR aPath, IN_BSTR aOpenMode, IN_BSTR aDisposition, IN_BSTR aSharingMode,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ULONG aCreationMode, LONG64 aOffset, IGuestFile **aFile)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No file to open specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aOpenMode) == NULL || *(aOpenMode) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No open mode specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aDisposition) == NULL || *(aDisposition) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No disposition mode specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* aSharingMode is optional. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo Validate creation mode. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = RTFileModeToFlagsEx(openInfo.mOpenMode.c_str(),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("Invalid open mode / disposition / sharing mode specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Return directory object to the caller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Handling guest files not supported by installed Guest Additions"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Opening guest file \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
6b022885f2cb6a55167609edecd89570cd80001dvboxsyncSTDMETHODIMP GuestSession::FileQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync return setError(E_INVALIDARG, tr("No file to query information for specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Element exists but is not a file"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information failed: %Rrc"), vrc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::FileQuerySize(IN_BSTR aPath, LONG64 *aSize)
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No file to query size for specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = fileQuerySizeInternal(Utf8Str(aPath), &llSize, &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = GuestProcess::setErrorExternal(this, guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file size failed: %Rrc"), vrc);
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncSTDMETHODIMP GuestSession::FileRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync return setError(E_INVALIDARG, tr("No source file to rename specified"));
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No destination file to rename the source to specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* No flags; only remove the directory when empty. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int vrc = pathRenameInternal(Utf8Str(aSource), Utf8Str(aDest), uFlags, &guestRc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Handling renaming guest files not supported by installed Guest Additions"));
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync /** @todo Proper guestRc to text translation needed. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Renaming guest file \"%s\" failed: %Rrc"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::FileSetACL(IN_BSTR aPath, IN_BSTR aACL)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::ProcessCreate(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, IGuestProcess **aProcess)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return ProcessCreateEx(aCommand, ComSafeArrayInArg(aArguments), ComSafeArrayInArg(aEnvironment),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinityIgnored), aProcess);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::ProcessCreateEx(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (RT_UNLIKELY((aCommand) == NULL || *(aCommand) == '\0'))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return setError(E_INVALIDARG, tr("No command to execute specified"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mArguments.push_back(Utf8Str(arguments[i]));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Create the process environment:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - Apply the session environment in a first step, and
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - Apply environment variables specified by this call to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * have the chance of overwriting/deleting session entries.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync procInfo.mEnvironment = mData.mEnvironment; /* Apply original session environment. */
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = procInfo.mEnvironment.Set(Utf8Str(environment[i]));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync com::SafeArray<ProcessCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync com::SafeArray<LONG> affinity(ComSafeArrayInArg(aAffinity));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Return guest session to the caller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of concurrent guest processes per session (%ld) reached"),
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync /** @todo Add more errors here. */
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest process, rc=%Rrc"), rc);
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsyncSTDMETHODIMP GuestSession::ProcessGet(ULONG aPID, IGuestProcess **aProcess)
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync return setError(E_INVALIDARG, tr("No valid process ID (PID) specified"));
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync hr = setError(E_INVALIDARG, tr("No process with PID %RU32 found"), aPID);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* This will set (*aProcess) to NULL if pProgress is NULL. */
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync LogFlowThisFunc(("aProcess=%p, hr=%Rhrc\n", *aProcess, hr));
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::SymlinkCreate(IN_BSTR aSource, IN_BSTR aTarget, SymlinkType_T aType)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::SymlinkExists(IN_BSTR aSymlink, BOOL *aExists)
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncSTDMETHODIMP GuestSession::SymlinkRead(IN_BSTR aSymlink, ComSafeArrayIn(SymlinkReadFlag_T, aFlags), BSTR *aTarget)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsyncSTDMETHODIMP GuestSession::SymlinkRemoveDirectory(IN_BSTR aPath)
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsyncSTDMETHODIMP GuestSession::SymlinkRemoveFile(IN_BSTR aFile)
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsyncSTDMETHODIMP GuestSession::WaitFor(ULONG aWaitFlags, ULONG aTimeoutMS, GuestSessionWaitResult_T *aReason)
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * Note: Do not hold any locks here while waiting!
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync int vrc = waitFor(aWaitFlags, aTimeoutMS, waitResult, &guestRc);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync hr = GuestSession::setErrorExternal(this, guestRc);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync const char *pszSessionName = mData.mSession.mName.c_str();
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync tr("Waiting for guest session \"%s\" failed: %Rrc"),
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync pszSessionName ? pszSessionName : tr("Unnamed"), vrc);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsyncSTDMETHODIMP GuestSession::WaitForArray(ComSafeArrayIn(GuestSessionWaitForFlag_T, aFlags), ULONG aTimeoutMS, GuestSessionWaitResult_T *aReason)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Note: Do not hold any locks here while waiting!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync com::SafeArray<GuestSessionWaitForFlag_T> flags(ComSafeArrayInArg(aFlags));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_GUEST_CONTROL */