/* $Id: GuestSessionImpl.h 98103 2023-01-17 14:15:46Z vboxsync $ */ /** @file * VirtualBox Main - Guest session handling. */ /* * Copyright (C) 2012-2023 Oracle and/or its affiliates. * * This file is part of VirtualBox base platform packages, as * available from https://www.virtualbox.org. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, in version 3 of the * License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * SPDX-License-Identifier: GPL-3.0-only */ #ifndef MAIN_INCLUDED_GuestSessionImpl_h #define MAIN_INCLUDED_GuestSessionImpl_h #ifndef RT_WITHOUT_PRAGMA_ONCE # pragma once #endif #include "GuestSessionWrap.h" #include "EventImpl.h" #include "GuestCtrlImplPrivate.h" #include "GuestProcessImpl.h" #include "GuestDirectoryImpl.h" #include "GuestFileImpl.h" #include "GuestFsObjInfoImpl.h" #include "GuestSessionImplTasks.h" #include /** @todo r=bird: Needed for ASMBitSet() in GuestSession::Data constructor. Removed when * that is moved into the class implementation file as it should be. */ #include class GuestSessionTaskInternalStart; /* Needed for i_startSessionThreadTask(). */ /** * Guest session implementation. */ class ATL_NO_VTABLE GuestSession : public GuestSessionWrap , public GuestBase { public: /** @name COM and internal init/term/mapping cruft. * @{ */ DECLARE_COMMON_CLASS_METHODS(GuestSession) int init(Guest *pGuest, const GuestSessionStartupInfo &ssInfo, const GuestCredentials &guestCreds); void uninit(void); HRESULT FinalConstruct(void); void FinalRelease(void); /** @} */ private: /** Wrapped @name IGuestSession properties. * @{ */ HRESULT getUser(com::Utf8Str &aUser); HRESULT getDomain(com::Utf8Str &aDomain); HRESULT getName(com::Utf8Str &aName); HRESULT getId(ULONG *aId); HRESULT getTimeout(ULONG *aTimeout); HRESULT setTimeout(ULONG aTimeout); HRESULT getProtocolVersion(ULONG *aProtocolVersion); HRESULT getStatus(GuestSessionStatus_T *aStatus); HRESULT getEnvironmentChanges(std::vector &aEnvironmentChanges); HRESULT setEnvironmentChanges(const std::vector &aEnvironmentChanges); HRESULT getEnvironmentBase(std::vector &aEnvironmentBase); HRESULT getProcesses(std::vector > &aProcesses); HRESULT getPathStyle(PathStyle_T *aPathStyle); HRESULT getCurrentDirectory(com::Utf8Str &aCurrentDirectory); HRESULT setCurrentDirectory(const com::Utf8Str &aCurrentDirectory); HRESULT getUserDocuments(com::Utf8Str &aUserDocuments); HRESULT getUserHome(com::Utf8Str &aUserHome); HRESULT getDirectories(std::vector > &aDirectories); HRESULT getFiles(std::vector > &aFiles); HRESULT getEventSource(ComPtr &aEventSource); /** @} */ /** Wrapped @name IGuestSession methods. * @{ */ HRESULT close(); HRESULT copyFromGuest(const std::vector &aSources, const std::vector &aFilters, const std::vector &aFlags, const com::Utf8Str &aDestination, ComPtr &aProgress); HRESULT copyToGuest(const std::vector &aSources, const std::vector &aFilters, const std::vector &aFlags, const com::Utf8Str &aDestination, ComPtr &aProgress); HRESULT directoryCopy(const com::Utf8Str &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT directoryCopyFromGuest(const com::Utf8Str &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT directoryCopyToGuest(const com::Utf8Str &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT directoryCreate(const com::Utf8Str &aPath, ULONG aMode, const std::vector &aFlags); HRESULT directoryCreateTemp(const com::Utf8Str &aTemplateName, ULONG aMode, const com::Utf8Str &aPath, BOOL aSecure, com::Utf8Str &aDirectory); HRESULT directoryExists(const com::Utf8Str &aPath, BOOL aFollowSymlinks, BOOL *aExists); HRESULT directoryOpen(const com::Utf8Str &aPath, const com::Utf8Str &aFilter, const std::vector &aFlags, ComPtr &aDirectory); HRESULT directoryRemove(const com::Utf8Str &aPath); HRESULT directoryRemoveRecursive(const com::Utf8Str &aPath, const std::vector &aFlags, ComPtr &aProgress); HRESULT environmentScheduleSet(const com::Utf8Str &aName, const com::Utf8Str &aValue); HRESULT environmentScheduleUnset(const com::Utf8Str &aName); HRESULT environmentGetBaseVariable(const com::Utf8Str &aName, com::Utf8Str &aValue); HRESULT environmentDoesBaseVariableExist(const com::Utf8Str &aName, BOOL *aExists); HRESULT fileCopy(const com::Utf8Str &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT fileCopyToGuest(const com::Utf8Str &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT fileCopyFromGuest(const com::Utf8Str &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT fileCreateTemp(const com::Utf8Str &aTemplateName, ULONG aMode, const com::Utf8Str &aPath, BOOL aSecure, ComPtr &aFile); HRESULT fileExists(const com::Utf8Str &aPath, BOOL aFollowSymlinks, BOOL *aExists); HRESULT fileOpen(const com::Utf8Str &aPath, FileAccessMode_T aAccessMode, FileOpenAction_T aOpenAction, ULONG aCreationMode, ComPtr &aFile); HRESULT fileOpenEx(const com::Utf8Str &aPath, FileAccessMode_T aAccessMode, FileOpenAction_T aOpenAction, FileSharingMode_T aSharingMode, ULONG aCreationMode, const std::vector &aFlags, ComPtr &aFile); HRESULT fileQuerySize(const com::Utf8Str &aPath, BOOL aFollowSymlinks, LONG64 *aSize); HRESULT fsQueryFreeSpace(const com::Utf8Str &aPath, LONG64 *aFreeSpace); HRESULT fsQueryInfo(const com::Utf8Str &aPath, ComPtr &aInfo); HRESULT fsObjExists(const com::Utf8Str &aPath, BOOL aFollowSymlinks, BOOL *pfExists); HRESULT fsObjQueryInfo(const com::Utf8Str &aPath, BOOL aFollowSymlinks, ComPtr &aInfo); HRESULT fsObjRemove(const com::Utf8Str &aPath); HRESULT fsObjRemoveArray(const std::vector &aPaths, ComPtr &aProgress); HRESULT fsObjRename(const com::Utf8Str &aOldPath, const com::Utf8Str &aNewPath, const std::vector &aFlags); HRESULT fsObjMove(const com::Utf8Str &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT fsObjMoveArray(const std::vector &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT fsObjCopyArray(const std::vector &aSource, const com::Utf8Str &aDestination, const std::vector &aFlags, ComPtr &aProgress); HRESULT fsObjSetACL(const com::Utf8Str &aPath, BOOL aFollowSymlinks, const com::Utf8Str &aAcl, ULONG aMode); HRESULT processCreate(const com::Utf8Str &aCommand, const std::vector &aArguments, const std::vector &aEnvironment, const std::vector &aFlags, ULONG aTimeoutMS, ComPtr &aGuestProcess); HRESULT processCreateEx(const com::Utf8Str &aCommand, const std::vector &aArguments, const std::vector &aEnvironment, const std::vector &aFlags, ULONG aTimeoutMS, ProcessPriority_T aPriority, const std::vector &aAffinity, ComPtr &aGuestProcess); HRESULT processGet(ULONG aPid, ComPtr &aGuestProcess); HRESULT symlinkCreate(const com::Utf8Str &aSource, const com::Utf8Str &aTarget, SymlinkType_T aType); HRESULT symlinkExists(const com::Utf8Str &aSymlink, BOOL *aExists); HRESULT symlinkRead(const com::Utf8Str &aSymlink, const std::vector &aFlags, com::Utf8Str &aTarget); HRESULT waitFor(ULONG aWaitFor, ULONG aTimeoutMS, GuestSessionWaitResult_T *aReason); HRESULT waitForArray(const std::vector &aWaitFor, ULONG aTimeoutMS, GuestSessionWaitResult_T *aReason); /** @} */ /** Map of guest directories. The key specifies the internal directory ID. */ typedef std::map > SessionDirectories; /** Map of guest files. The key specifies the internal file ID. */ typedef std::map > SessionFiles; /** Map of guest processes. The key specifies the internal process number. * To retrieve the process' guest PID use the Id() method of the IProcess interface. */ typedef std::map > SessionProcesses; /** Guest session object type enumeration. */ enum SESSIONOBJECTTYPE { /** Invalid session object type. */ SESSIONOBJECTTYPE_INVALID = 0, /** Session object. */ SESSIONOBJECTTYPE_SESSION = 1, /** Directory object. */ SESSIONOBJECTTYPE_DIRECTORY = 2, /** File object. */ SESSIONOBJECTTYPE_FILE = 3, /** Process object. */ SESSIONOBJECTTYPE_PROCESS = 4 }; struct SessionObject { /** Creation timestamp (in ms). * @note not used by anyone at the moment. */ uint64_t msBirth; /** The object type. */ SESSIONOBJECTTYPE enmType; /** Weak pointer to the object itself. * Is NULL for SESSIONOBJECTTYPE_SESSION because GuestSession doesn't * inherit from GuestObject. */ GuestObject *pObject; }; /** Map containing all objects bound to a guest session. * The key specifies the (global) context ID. */ typedef std::map SessionObjects; public: /** @name Public internal methods. * @todo r=bird: Most of these are public for no real reason... * @{ */ HRESULT i_copyFromGuest(const GuestSessionFsSourceSet &SourceSet, const com::Utf8Str &strDestination, ComPtr &pProgress); HRESULT i_copyToGuest(const GuestSessionFsSourceSet &SourceSet, const com::Utf8Str &strDestination, ComPtr &pProgress); int i_closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc); HRESULT i_directoryCopyFlagFromStr(const com::Utf8Str &strFlags, bool fStrict, DirectoryCopyFlag_T *pfFlags); bool i_directoryExists(const Utf8Str &strPath); inline bool i_directoryExists(uint32_t uDirID, ComObjPtr *pDir); int i_directoryUnregister(GuestDirectory *pDirectory); int i_directoryRemove(const Utf8Str &strPath, uint32_t fFlags, int *pGuestRc); int i_directoryCreate(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc); int i_directoryOpen(const GuestDirectoryOpenInfo &openInfo, ComObjPtr &pDirectory, int *pGuestRc); int i_directoryQueryInfo(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc); int i_dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); int i_dispatchToThis(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb); HRESULT i_fileCopyFlagFromStr(const com::Utf8Str &strFlags, bool fStrict, FileCopyFlag_T *pfFlags); inline bool i_fileExists(uint32_t uFileID, ComObjPtr *pFile); int i_fileUnregister(GuestFile *pFile); int i_fileRemove(const Utf8Str &strPath, int *pGuestRc); int i_fileOpenEx(const com::Utf8Str &aPath, FileAccessMode_T aAccessMode, FileOpenAction_T aOpenAction, FileSharingMode_T aSharingMode, ULONG aCreationMode, const std::vector &aFlags, ComObjPtr &pFile, int *prcGuest); int i_fileOpen(const GuestFileOpenInfo &openInfo, ComObjPtr &pFile, int *pGuestRc); int i_fileQueryInfo(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc); int i_fileQuerySize(const Utf8Str &strPath, bool fFollowSymlinks, int64_t *pllSize, int *pGuestRc); int i_fsCreateTemp(const Utf8Str &strTemplate, const Utf8Str &strPath, bool fDirectory, Utf8Str &strName, uint32_t fMode, bool fSecure, int *pGuestRc); int i_fsQueryInfo(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc); const GuestCredentials &i_getCredentials(void); EventSource *i_getEventSource(void) { return mEventSource; } Utf8Str i_getName(void); ULONG i_getId(void) { return mData.mSession.mID; } bool i_isStarted(void) const; HRESULT i_isStartedExternal(void); bool i_isTerminated(void) const; int i_onRemove(void); int i_onSessionStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); PathStyle_T i_getGuestPathStyle(void); static PathStyle_T i_getHostPathStyle(void); int i_startSession(int *pGuestRc); int i_startSessionAsync(void); Guest *i_getParent(void) { return mParent; } uint32_t i_getProtocolVersion(void) { return mData.mProtocolVersion; } int i_objectRegister(GuestObject *pObject, SESSIONOBJECTTYPE enmType, uint32_t *pidObject); int i_objectUnregister(uint32_t uObjectID); int i_objectsUnregister(void); int i_objectsNotifyAboutStatusChange(GuestSessionStatus_T enmSessionStatus); int i_pathRename(const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags, int *pGuestRc); int i_pathUserDocuments(Utf8Str &strPath, int *prcGuest); int i_pathUserHome(Utf8Str &strPath, int *prcGuest); int i_processUnregister(GuestProcess *pProcess); int i_processCreateEx(GuestProcessStartupInfo &procInfo, ComObjPtr &pProgress); inline bool i_processExists(uint32_t uProcessID, ComObjPtr *pProcess); inline int i_processGetByPID(ULONG uPID, ComObjPtr *pProcess); int i_sendMessage(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms, uint64_t fDst = VBOX_GUESTCTRL_DST_SESSION); int i_setSessionStatus(GuestSessionStatus_T sessionStatus, int sessionRc); int i_signalWaiters(GuestSessionWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS */); int i_shutdown(uint32_t fFlags, int *prcGuest); int i_determineProtocolVersion(void); int i_waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestSessionWaitResult_T &waitResult, int *pGuestRc); int i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS, GuestSessionStatus_T *pSessionStatus, int *pGuestRc); /** @} */ public: /** @name Static helper methods. * @{ */ static Utf8Str i_guestErrorToString(int guestRc); static bool i_isTerminated(GuestSessionStatus_T enmStatus); static int i_startSessionThreadTask(GuestSessionTaskInternalStart *pTask); /** @} */ private: /** Pointer to the parent (Guest). */ Guest *mParent; /** * The session's event source. This source is used for * serving the internal listener as well as all other * external listeners that may register to it. * * Note: This can safely be used without holding any locks. * An AutoCaller suffices to prevent it being destroy while in use and * internally there is a lock providing the necessary serialization. */ const ComObjPtr mEventSource; /** @todo r=bird: One of the core points of the DATA sub-structures in Main is * hinding implementation details and stuff that requires including iprt/asm.h. * The way it's used here totally defeats that purpose. You need to make it * a pointer to a anynmous Data struct and define that structure in * GuestSessionImpl.cpp and allocate it in the Init() function. */ struct Data { /** The session credentials. */ GuestCredentials mCredentials; /** The session's startup info. */ GuestSessionStartupInfo mSession; /** The session's object ID. * Needed for registering wait events which are bound directly to this session. */ uint32_t mObjectID; /** The session's current status. */ GuestSessionStatus_T mStatus; /** The set of environment changes for the session for use when * creating new guest processes. */ GuestEnvironmentChanges mEnvironmentChanges; /** Pointer to the immutable base environment for the session. * @note This is not allocated until the guest reports it to the host. It is * also shared with child processes. * @todo This is actually not yet implemented, see * GuestSession::i_onSessionStatusChange. */ GuestEnvironment const *mpBaseEnvironment; /** Directory objects bound to this session. */ SessionDirectories mDirectories; /** File objects bound to this session. */ SessionFiles mFiles; /** Process objects bound to this session. */ SessionProcesses mProcesses; /** Map of registered session objects (files, directories, ...). */ SessionObjects mObjects; /** Guest control protocol version to be used. * Guest Additions < VBox 4.3 have version 1, * any newer version will have version 2. */ uint32_t mProtocolVersion; /** Session timeout (in ms). */ uint32_t mTimeout; /** The last returned session status * returned from the guest side. */ int mRC; /** Object ID allocation bitmap; clear bits are free, set bits are busy. */ uint64_t bmObjectIds[VBOX_GUESTCTRL_MAX_OBJECTS / sizeof(uint64_t) / 8]; Data(void) : mpBaseEnvironment(NULL) { RT_ZERO(bmObjectIds); ASMBitSet(&bmObjectIds, VBOX_GUESTCTRL_MAX_OBJECTS - 1); /* Reserved for the session itself? */ ASMBitSet(&bmObjectIds, 0); /* Let's reserve this too. */ } Data(const Data &rThat) : mCredentials(rThat.mCredentials) , mSession(rThat.mSession) , mStatus(rThat.mStatus) , mEnvironmentChanges(rThat.mEnvironmentChanges) , mpBaseEnvironment(NULL) , mDirectories(rThat.mDirectories) , mFiles(rThat.mFiles) , mProcesses(rThat.mProcesses) , mObjects(rThat.mObjects) , mProtocolVersion(rThat.mProtocolVersion) , mTimeout(rThat.mTimeout) , mRC(rThat.mRC) { memcpy(&bmObjectIds, &rThat.bmObjectIds, sizeof(bmObjectIds)); } ~Data(void) { if (mpBaseEnvironment) { mpBaseEnvironment->releaseConst(); mpBaseEnvironment = NULL; } } } mData; }; #endif /* !MAIN_INCLUDED_GuestSessionImpl_h */