儲存庫 vbox 的更動 42160
- 時間撮記:
- 2012-7-16 上午11:41:10 (12 年 以前)
- 位置:
- trunk
- 檔案:
-
- 修改 11 筆資料
- 移動 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/include/VBox/HostServices/GuestControlSvc.h
r39906 r42160 4 4 5 5 /* 6 * Copyright (C) 2011 Oracle Corporation6 * Copyright (C) 2011-2012 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 73 73 * Note: Has to match Main's ProcessInputFlag_* flags! 74 74 */ 75 #define INPUT_FLAG_NONE 076 #define INPUT_FLAG_EOF RT_BIT(0)75 #define INPUT_FLAG_NONE 0x0 76 #define INPUT_FLAG_EOF RT_BIT(0) 77 77 78 78 /** 79 79 * Execution flags. 80 * Note: Has to match Main's ExecuteProcessFlag_* flags!80 * Note: Has to match Main's CreateProcessFlag_* flags! 81 81 */ 82 82 #define EXECUTEPROCESSFLAG_NONE 0x0 -
trunk/src/VBox/Main/Makefile.kmk
r42154 r42160 620 620 src-client/GuestSessionImpl.cpp \ 621 621 src-client/GuestCtrlImpl.cpp \ 622 src-client/GuestCtrlIO.cpp \623 622 src-client/GuestCtrlImplDir.cpp \ 624 623 src-client/GuestCtrlImplFile.cpp \ … … 641 640 ifdef VBOX_WITH_GUEST_CONTROL 642 641 VBoxC_SOURCES += \ 642 src-client/GuestCtrlPrivate.cpp \ 643 643 src-client/GuestCtrlImplTasks.cpp \ 644 644 src-client/GuestDirEntryImpl.cpp -
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r40575 r42160 1 1 /** @file 2 2 * 3 * VirtualBox Guest Control - Private data definitions / classes.3 * Internal helpers/structures for guest control functionality. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2011 Oracle Corporation7 * Copyright (C) 2011-2012 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 19 19 #define ____H_GUESTIMPLPRIVATE 20 20 21 #include <iprt/semaphore.h> 22 21 23 #include <VBox/com/com.h> 24 #include <VBox/com/ErrorInfo.h> 22 25 #include <VBox/com/string.h> 23 26 #include <VBox/com/VirtualBox.h> … … 33 36 #endif 34 37 35 class Guest; 36 class Progress; 37 38 /** Structure representing the "value" side of a "key=value" pair. */ 38 39 /* Builds a context ID out of the session ID, process ID and an 40 * increasing count. */ 41 #define VBOX_GUESTCTRL_CONTEXTID_MAKE(uSession, uProcess, uCount) \ 42 ( (uint32_t)((uSession) & 0xff) << 24 \ 43 | (uint32_t)((uProcess) & 0xff) << 16 \ 44 | (uint32_t)((uCount) & 0xffff) \ 45 ) 46 47 48 typedef std::vector <LONG> ProcessAffinity; 49 typedef std::vector <Utf8Str> ProcessArguments; 50 typedef std::map <Utf8Str, Utf8Str> ProcessEnvironmentMap; 51 52 53 /** 54 * Generic class for a all guest control callbacks. 55 */ 56 class GuestCtrlCallback 57 { 58 public: 59 60 GuestCtrlCallback(void); 61 62 GuestCtrlCallback(eVBoxGuestCtrlCallbackType enmType); 63 64 virtual ~GuestCtrlCallback(void); 65 66 /** @todo Copy/comparison operator? */ 67 68 public: 69 70 int Init(eVBoxGuestCtrlCallbackType enmType); 71 72 void Destroy(void); 73 74 eVBoxGuestCtrlCallbackType Type(void); 75 76 int Wait(RTMSINTERVAL timeoutMS); 77 78 protected: 79 80 /** The callback type. */ 81 eVBoxGuestCtrlCallbackType mType; 82 /** Callback flags. */ 83 uint32_t mFlags; 84 /** Pointer to user-supplied data. */ 85 void *pvData; 86 /** Size of user-supplied data. */ 87 size_t cbData; 88 /** The event semaphore triggering the*/ 89 RTSEMEVENT mEventSem; 90 /** Extended error information, if any. */ 91 ErrorInfo mErrorInfo; 92 }; 93 typedef std::map <uint32_t, GuestCtrlCallback> GuestCtrlCallbacks; 94 95 /** 96 * Simple structure mantaining guest credentials. 97 */ 98 class GuestCredentials 99 { 100 public: 101 102 103 public: 104 105 Utf8Str mUser; 106 Utf8Str mPassword; 107 Utf8Str mDomain; 108 }; 109 110 /** 111 * Structure for keeping all the relevant process 112 * starting parameters around. 113 */ 114 struct GuestProcessInfo 115 { 116 Utf8Str mCommand; 117 ProcessArguments mArguments; 118 ProcessEnvironmentMap mEnvironment; 119 uint32_t mFlags; 120 ULONG mTimeoutMS; 121 ProcessPriority_T mPriority; 122 ProcessAffinity mAffinity; 123 }; 124 125 /** 126 * Class representing the "value" side of a "key=value" pair. 127 */ 39 128 class GuestProcessStreamValue 40 129 { … … 144 233 BYTE *m_pbBuffer; 145 234 }; 235 236 class Guest; 237 class Progress; 146 238 147 239 class GuestTask -
trunk/src/VBox/Main/include/GuestImpl.h
r42105 r42160 4 4 5 5 /* 6 * Copyright (C) 2006-201 1Oracle Corporation6 * Copyright (C) 2006-2012 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 205 205 /** @name Public internal methods. 206 206 * @{ */ 207 int sessionClose(ComObjPtr<GuestSession> pSession); 207 Console *getConsole(void) { return mParent; } 208 int sessionClose(ComObjPtr<GuestSession> pSession); 209 int sessionCreate(const Utf8Str &strUser, const Utf8Str &aPassword, const Utf8Str &aDomain, 210 const Utf8Str &aSessionName, IGuestSession **aGuestSession); 211 inline bool sessionExists(uint32_t uSessionID); 208 212 /** @} */ 209 213 … … 303 307 typedef std::map< AdditionsFacilityType_T, ComObjPtr<AdditionsFacility> >::const_iterator FacilityMapIterConst; 304 308 305 typedef std::list <ComObjPtr<GuestSession> > GuestSessions; 309 /** Map for keeping the guest sessions. The primary key marks the guest session ID. */ 310 typedef std::map <uint32_t, ComObjPtr<GuestSession> > GuestSessions; 306 311 307 312 struct Data … … 320 325 Bstr mInterfaceVersion; 321 326 GuestSessions mGuestSessions; 327 uint32_t mNextSessionID; 322 328 }; 323 329 -
trunk/src/VBox/Main/include/GuestProcessImpl.h
r42117 r42160 21 21 22 22 #include "VirtualBoxBase.h" 23 #include "GuestCtrlImplPrivate.h" 23 24 24 #include <vector> 25 26 typedef std::vector<Utf8Str> StringsArray; 27 25 class Console; 28 26 class GuestSession; 29 27 … … 47 45 DECLARE_EMPTY_CTOR_DTOR(GuestProcess) 48 46 49 int init(GuestSession *pSession, 50 const Utf8Str &aCommand, const StringsArray &aArguments, const StringsArray &aEnvironment, 51 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, 52 ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity)); 47 int init(Console *aConsole, GuestSession *aSession, uint32_t aProcessID, const GuestProcessInfo &aProcInfo); 53 48 void uninit(void); 54 49 HRESULT FinalConstruct(void); … … 74 69 /** @name Public internal methods. 75 70 * @{ */ 71 int callbackAdd(const GuestCtrlCallback& theCallback, uint32_t *puContextID); 72 bool callbackExists(uint32_t uContextID); 73 bool isReady(void); 74 int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnvVars); 75 int readData(ULONG aHandle, ULONG aSize, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData)); 76 int startProcess(void); 77 static DECLCALLBACK(int) GuestProcess::startProcessThread(RTTHREAD Thread, void *pvUser); 78 int terminateProcess(void); 79 int waitFor(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitReason_T *aReason); 80 int writeData(ULONG aHandle, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten); 76 81 /** @} */ 77 82 78 83 private: 79 84 80 typedef std::map <Utf8Str, Utf8Str> MyStringMap;81 82 85 struct Data 83 86 { 84 GuestSession *mParent; 85 Bstr mName; 87 /** Pointer to parent session. */ 88 GuestSession *mParent; 89 /** Pointer to the console object. Needed 90 * for HGCM (VMMDev) communication. */ 91 Console *mConsole; 92 /** All related callbacks to this process. */ 93 GuestCtrlCallbacks mCallbacks; 94 /** The process start information. */ 95 GuestProcessInfo mProcess; 96 /** Exit code if process has been terminated. */ 97 LONG mExitCode; 98 /** PID reported from the guest. */ 99 ULONG mPID; 100 /** Internal, host-side process ID. */ 101 uint32_t mProcessID; 102 /** The current process status. */ 103 ProcessStatus_T mStatus; 104 /** Flag indicating whether the process has been started. */ 105 bool mStarted; 106 /** The next upcoming context ID. */ 107 uint32_t mNextContextID; 86 108 } mData; 87 109 }; -
trunk/src/VBox/Main/include/GuestSessionImpl.h
r42117 r42160 22 22 #include "VirtualBoxBase.h" 23 23 24 #include "GuestCtrlImplPrivate.h" 24 25 #include "GuestProcessImpl.h" 25 26 #include "GuestDirectoryImpl.h" 26 27 #include "GuestFileImpl.h" 27 28 #include "GuestFsObjInfoImpl.h" 28 29 #include <map>30 #include <vector>31 32 typedef std::vector<Utf8Str> StringsArray;33 29 34 30 class Guest; … … 52 48 DECLARE_EMPTY_CTOR_DTOR(GuestSession) 53 49 54 int init(Guest *aGuest, Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName);50 int init(Guest *aGuest, uint32_t aSessionID, Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName); 55 51 void uninit(void); 56 52 HRESULT FinalConstruct(void); … … 115 111 /** @name Public internal methods. 116 112 * @{ */ 117 int directoryClose(ComObjPtr<GuestDirectory> pDirectory); 118 int fileClose(ComObjPtr<GuestFile> pFile); 119 int processClose(ComObjPtr<GuestProcess> pProcess); 120 int processCreateExInteral(const Utf8Str &aCommand, const StringsArray &aArguments, const StringsArray &aEnvironment, 121 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, 122 ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity), 123 IGuestProcess **aProcess); 113 int directoryClose(ComObjPtr<GuestDirectory> pDirectory); 114 int fileClose(ComObjPtr<GuestFile> pFile); 115 const GuestCredentials &getCredentials(void); 116 int processClose(ComObjPtr<GuestProcess> pProcess); 117 int processCreateExInteral(GuestProcessInfo &aProcInfo, IGuestProcess **aProcess); 118 inline bool processExists(uint32_t uProcessID); 124 119 /** @} */ 125 120 … … 128 123 typedef std::map <Utf8Str, Utf8Str> SessionEnvironment; 129 124 130 typedef std:: list<ComObjPtr<GuestDirectory> > SessionDirectories;131 typedef std:: list<ComObjPtr<GuestFile> > SessionFiles;132 typedef std:: list <ComObjPtr<GuestProcess> > SessionProcesses;125 typedef std::vector <ComObjPtr<GuestDirectory> > SessionDirectories; 126 typedef std::vector <ComObjPtr<GuestFile> > SessionFiles; 127 typedef std::map <uint32_t, ComObjPtr<GuestProcess> > SessionProcesses; 133 128 134 129 struct Data … … 137 132 * or not. Internal session are not accessible by clients. */ 138 133 bool fInternal; 139 /** Pointer to the parent ( IGuest). */134 /** Pointer to the parent (Guest). */ 140 135 Guest *mParent; 141 136 /** The session credentials. */ 142 Utf8Str mUser; 143 Utf8Str mPassword; 144 Utf8Str mDomain; 137 GuestCredentials mCredentials; 145 138 /** The (optional) session name. */ 146 139 Utf8Str mName; -
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r42105 r42160 2671 2671 itSessions != mData.mGuestSessions.end(); ++itSessions) 2672 2672 { 2673 if (pSession == (*itSessions))2674 { 2675 mData.mGuestSessions. remove((*itSessions));2673 if (pSession == itSessions->second) 2674 { 2675 mData.mGuestSessions.erase(itSessions); 2676 2676 return VINF_SUCCESS; 2677 2677 } … … 2679 2679 2680 2680 return VERR_NOT_FOUND; 2681 } 2682 2683 int Guest::sessionCreate(const Utf8Str &strUser, const Utf8Str &strPassword, const Utf8Str &strDomain, 2684 const Utf8Str &strSessionName, IGuestSession **aGuestSession) 2685 { 2686 AssertPtrReturn(aGuestSession, VERR_INVALID_POINTER); 2687 2688 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2689 2690 int rc = VERR_MAX_PROCS_REACHED; 2691 ComObjPtr<GuestSession> pGuestSession; 2692 try 2693 { 2694 /* Create a new session ID and assign it. */ 2695 uint32_t uNewSessionID = 0; 2696 uint32_t uTries = 0; 2697 2698 for (;;) 2699 { 2700 /* Is the context ID already used? Try next ID ... */ 2701 if (!sessionExists(uNewSessionID++)) 2702 { 2703 /* Callback with context ID was not found. This means 2704 * we can use this context ID for our new callback we want 2705 * to add below. */ 2706 rc = VINF_SUCCESS; 2707 break; 2708 } 2709 2710 if (++uTries == UINT32_MAX) 2711 break; /* Don't try too hard. */ 2712 } 2713 if (RT_FAILURE(rc)) throw rc; 2714 2715 /* Create the session object. */ 2716 HRESULT hr = pGuestSession.createObject(); 2717 if (FAILED(hr)) throw VERR_COM_UNEXPECTED; 2718 2719 rc = pGuestSession->init(this, uNewSessionID, 2720 strUser, strPassword, strDomain, strSessionName); 2721 if (RT_FAILURE(rc)) throw VBOX_E_IPRT_ERROR; 2722 2723 mData.mGuestSessions[uNewSessionID] = pGuestSession; 2724 2725 /* Return guest session to the caller. */ 2726 hr = pGuestSession.queryInterfaceTo(aGuestSession); 2727 if (FAILED(hr)) throw VERR_COM_OBJECT_NOT_FOUND; 2728 } 2729 catch (int rc2) 2730 { 2731 rc = rc2; 2732 } 2733 2734 return rc; 2735 } 2736 2737 inline bool Guest::sessionExists(uint32_t uSessionID) 2738 { 2739 AssertReturn(uSessionID, false); 2740 2741 GuestSessions::const_iterator itSessions = mData.mGuestSessions.find(uSessionID); 2742 return (itSessions == mData.mGuestSessions.end()) ? false : true; 2681 2743 } 2682 2744 … … 2698 2760 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2699 2761 2700 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2701 2702 HRESULT hr; 2703 ComObjPtr<GuestSession> pGuestSession; 2704 try 2705 { 2706 /* Create the session object. */ 2707 hr = pGuestSession.createObject(); 2708 if (FAILED(hr)) throw hr; 2709 2710 int rc = pGuestSession->init(this, 2711 aUser, aPassword, aDomain, aSessionName); 2712 if (RT_FAILURE(rc)) throw VBOX_E_IPRT_ERROR; 2713 2714 mData.mGuestSessions.push_back(pGuestSession); 2715 2716 /* Return guest session to the caller. */ 2717 hr = pGuestSession.queryInterfaceTo(aGuestSession); 2718 } 2719 catch (HRESULT aRC) 2720 { 2721 hr = aRC; 2722 } 2723 2724 return hr; 2762 2725 2763 #endif /* VBOX_WITH_GUEST_CONTROL */ 2726 2764 } -
trunk/src/VBox/Main/src-client/GuestCtrlImplTasks.cpp
r40685 r42160 49 49 } 50 50 51 GuestTask::~GuestTask( )51 GuestTask::~GuestTask(void) 52 52 { 53 53 54 54 } 55 55 56 int GuestTask::startThread( )56 int GuestTask::startThread(void) 57 57 { 58 58 return RTThreadCreate(NULL, GuestTask::taskThread, this, -
trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
r42121 r42160 2 2 /** @file 3 3 * 4 * I O helper for IGuest COM class implementations.4 * Internal helpers/structures for guest control functionality. 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 2011 Oracle Corporation8 * Copyright (C) 2011-2012 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 30 30 ******************************************************************************/ 31 31 32 GuestCtrlCallback::GuestCtrlCallback(void) 33 : mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN), 34 pvData(NULL), 35 cbData(0), 36 mEventSem(NIL_RTSEMEVENT) 37 { 38 } 39 40 GuestCtrlCallback::GuestCtrlCallback(eVBoxGuestCtrlCallbackType enmType) 41 : mType(VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN), 42 pvData(NULL), 43 cbData(0), 44 mEventSem(NIL_RTSEMEVENT) 45 { 46 int rc = Init(enmType); 47 AssertRC(rc); 48 } 49 50 GuestCtrlCallback::~GuestCtrlCallback(void) 51 { 52 Destroy(); 53 } 54 55 int GuestCtrlCallback::Init(eVBoxGuestCtrlCallbackType enmType) 56 { 57 AssertReturn(enmType > VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN, VERR_INVALID_PARAMETER); 58 Assert((pvData == NULL) && !cbData); 59 60 int rc = VINF_SUCCESS; 61 switch (enmType) 62 { 63 case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START: 64 { 65 pvData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS)); 66 AssertPtrReturn(pvData, VERR_NO_MEMORY); 67 RT_BZERO(pvData, sizeof(CALLBACKDATAEXECSTATUS)); 68 cbData = sizeof(CALLBACKDATAEXECSTATUS); 69 break; 70 } 71 72 case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT: 73 { 74 pvData = (PCALLBACKDATAEXECOUT)RTMemAlloc(sizeof(CALLBACKDATAEXECOUT)); 75 AssertPtrReturn(pvData, VERR_NO_MEMORY); 76 RT_BZERO(pvData, sizeof(CALLBACKDATAEXECOUT)); 77 cbData = sizeof(CALLBACKDATAEXECOUT); 78 break; 79 } 80 81 case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS: 82 { 83 PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECINSTATUS)); 84 AssertPtrReturn(pData, VERR_NO_MEMORY); 85 RT_BZERO(pData, sizeof(CALLBACKDATAEXECINSTATUS)); 86 cbData = sizeof(CALLBACKDATAEXECINSTATUS); 87 break; 88 } 89 90 default: 91 AssertMsgFailed(("Unknown callback type specified (%d)\n", enmType)); 92 break; 93 } 94 95 if (RT_SUCCESS(rc)) 96 { 97 rc = RTSemEventCreate(&mEventSem); 98 if (RT_SUCCESS(rc)) 99 mType = enmType; 100 } 101 102 return rc; 103 } 104 105 void GuestCtrlCallback::Destroy(void) 106 { 107 mType = VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN; 108 if (pvData) 109 { 110 RTMemFree(pvData); 111 pvData = NULL; 112 } 113 cbData = 0; 114 if (mEventSem != NIL_RTSEMEVENT) 115 RTSemEventDestroy(mEventSem); 116 } 117 118 eVBoxGuestCtrlCallbackType GuestCtrlCallback::Type(void) 119 { 120 return mType; 121 } 122 123 int GuestCtrlCallback::Wait(RTMSINTERVAL timeoutMS) 124 { 125 Assert(mEventSem != NIL_RTSEMEVENT); 126 return RTSemEventWait(mEventSem, timeoutMS); 127 } 128 129 /////////////////////////////////////////////////////////////////////////////// 130 32 131 /** @todo *NOT* thread safe yet! */ 33 132 /** @todo Add exception handling for STL stuff! */ 34 133 35 GuestProcessStreamBlock::GuestProcessStreamBlock( )134 GuestProcessStreamBlock::GuestProcessStreamBlock(void) 36 135 { 37 136 … … 223 322 /////////////////////////////////////////////////////////////////////////////// 224 323 225 GuestProcessStream::GuestProcessStream( )324 GuestProcessStream::GuestProcessStream(void) 226 325 : m_cbAllocated(0), 227 326 m_cbSize(0), … … 232 331 } 233 332 234 GuestProcessStream::~GuestProcessStream( )333 GuestProcessStream::~GuestProcessStream(void) 235 334 { 236 335 Destroy(); … … 311 410 * Destroys the internal data buffer. 312 411 */ 313 void GuestProcessStream::Destroy( )412 void GuestProcessStream::Destroy(void) 314 413 { 315 414 if (m_pbBuffer) -
trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
r42117 r42160 22 22 *******************************************************************************/ 23 23 #include "GuestProcessImpl.h" 24 #include "GuestSessionImpl.h" 25 #include "ConsoleImpl.h" 24 26 25 27 #include "Global.h" 26 28 #include "AutoCaller.h" 27 29 #include "Logging.h" 30 #include "VMMDev.h" 31 32 #include <iprt/asm.h> 33 #include <iprt/getopt.h> 34 #include <VBox/VMMDev.h> 35 #include <VBox/com/array.h> 36 37 38 struct GuestProcessTask 39 { 40 GuestProcessTask(GuestProcess *pProcess) 41 : mProcess(pProcess) { } 42 43 ~GuestProcessTask(void) { } 44 45 int rc() const { return mRC; } 46 bool isOk() const { return RT_SUCCESS(rc()); } 47 48 const ComObjPtr<GuestProcess> mProcess; 49 50 private: 51 int mRC; 52 }; 53 54 struct GuestProcessStartTask : public GuestProcessTask 55 { 56 GuestProcessStartTask(GuestProcess *pProcess) 57 : GuestProcessTask(pProcess) { } 58 }; 28 59 29 60 … … 36 67 { 37 68 LogFlowThisFunc(("\n")); 69 70 mData.mExitCode = 0; 71 mData.mNextContextID = 0; 72 mData.mPID = 0; 73 mData.mProcessID = 0; 74 mData.mStatus = ProcessStatus_Undefined; 75 mData.mStarted = false; 76 38 77 return BaseFinalConstruct(); 39 78 } … … 50 89 ///////////////////////////////////////////////////////////////////////////// 51 90 52 int GuestProcess::init(GuestSession *pSession, 53 const Utf8Str &aCommand, const StringsArray &aArguments, const StringsArray &aEnvironment, 54 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, 55 ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity)) 56 { 91 int GuestProcess::init(Console *aConsole, GuestSession *aSession, uint32_t aProcessID, const GuestProcessInfo &aProcInfo) 92 { 93 AssertPtrReturn(aSession, VERR_INVALID_POINTER); 94 57 95 /* Enclose the state transition NotReady->InInit->Ready. */ 58 96 AutoInitSpan autoInitSpan(this); 59 97 AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED); 60 98 61 int rc = VINF_SUCCESS; 62 63 mData.mParent = pSession; 64 65 /* Confirm a successful initialization when it's the case. */ 99 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 100 101 mData.mConsole = aConsole; 102 mData.mParent = aSession; 103 mData.mProcessID = aProcessID; 104 mData.mStatus = ProcessStatus_Starting; 105 /* Everything else will be set by the actual starting routine. */ 106 107 /* Asynchronously start the process on the guest by kicking off a 108 * worker thread. */ 109 std::auto_ptr<GuestProcessStartTask> pTask(new GuestProcessStartTask(this)); 110 AssertReturn(pTask->isOk(), pTask->rc()); 111 112 int rc = RTThreadCreate(NULL, GuestProcess::startProcessThread, 113 (void *)pTask.get(), 0, 114 RTTHREADTYPE_MAIN_WORKER, 0, 115 "gctlPrcStart"); 66 116 if (RT_SUCCESS(rc)) 117 { 118 /* task is now owned by startProcessThread(), so release it. */ 119 pTask.release(); 120 121 /* Confirm a successful initialization when it's the case. */ 67 122 autoInitSpan.setSucceeded(); 123 } 68 124 69 125 return rc; … … 97 153 CheckComArgOutSafeArrayPointerValid(aArguments); 98 154 99 ReturnComNotImplemented(); 155 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 156 157 com::SafeArray<BSTR> collection(mData.mProcess.mArguments.size()); 158 size_t s = 0; 159 for (ProcessArguments::const_iterator it = mData.mProcess.mArguments.begin(); 160 it != mData.mProcess.mArguments.end(); 161 ++it, ++s) 162 { 163 collection[s] = Bstr((*it)).raw(); 164 } 165 166 collection.detachTo(ComSafeArrayOutArg(aArguments)); 167 168 return S_OK; 100 169 #endif /* VBOX_WITH_GUEST_CONTROL */ 101 170 } … … 111 180 CheckComArgOutSafeArrayPointerValid(aEnvironment); 112 181 113 ReturnComNotImplemented(); 182 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 183 184 com::SafeArray<BSTR> collection(mData.mProcess.mEnvironment.size()); 185 size_t s = 0; 186 for (ProcessEnvironmentMap::const_iterator it = mData.mProcess.mEnvironment.begin(); 187 it != mData.mProcess.mEnvironment.end(); 188 ++it, ++s) 189 { 190 collection[s] = Bstr(it->first + "=" + it->second).raw(); 191 } 192 193 collection.detachTo(ComSafeArrayOutArg(aEnvironment)); 194 195 return S_OK; 114 196 #endif /* VBOX_WITH_GUEST_CONTROL */ 115 197 } … … 123 205 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 124 206 125 ReturnComNotImplemented(); 207 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 208 209 mData.mProcess.mCommand.cloneTo(aExecutablePath); 210 211 return S_OK; 126 212 #endif /* VBOX_WITH_GUEST_CONTROL */ 127 213 } … … 135 221 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 136 222 137 ReturnComNotImplemented(); 223 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 224 225 *aExitCode = mData.mExitCode; 226 227 return S_OK; 138 228 #endif /* VBOX_WITH_GUEST_CONTROL */ 139 229 } … … 147 237 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 148 238 149 ReturnComNotImplemented(); 239 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 240 241 *aPID = mData.mPID; 242 243 return S_OK; 150 244 #endif /* VBOX_WITH_GUEST_CONTROL */ 151 245 } … … 159 253 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 160 254 161 ReturnComNotImplemented(); 162 #endif /* VBOX_WITH_GUEST_CONTROL */ 255 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 256 257 *aStatus = mData.mStatus; 258 259 return S_OK; 260 #endif /* VBOX_WITH_GUEST_CONTROL */ 261 } 262 263 // private methods 264 ///////////////////////////////////////////////////////////////////////////// 265 266 /* 267 268 SYNC TO ASK: 269 Everything which involves HGCM communication (start, read/write/status(?)/...) 270 either can be called synchronously or asynchronously by running in a Main worker 271 thread. 272 273 Rules: 274 - Only one async operation per process a time can be around. 275 276 */ 277 278 int GuestProcess::callbackAdd(const GuestCtrlCallback& theCallback, uint32_t *puContextID) 279 { 280 const ComObjPtr<GuestSession> pSession(mData.mParent); 281 Assert(!pSession.isNull()); 282 ULONG uSessionID = 0; 283 HRESULT hr = pSession->COMGETTER(Id)(&uSessionID); 284 ComAssertComRC(hr); 285 286 /* Create a new context ID and assign it. */ 287 int rc = VERR_NOT_FOUND; 288 uint32_t uNewContextID = 0; 289 uint32_t uTries = 0; 290 for (;;) 291 { 292 /* Create a new context ID ... */ 293 uNewContextID = VBOX_GUESTCTRL_CONTEXTID_MAKE(uSessionID, 294 mData.mProcessID, ASMAtomicIncU32(&mData.mNextContextID)); 295 if (uNewContextID == UINT32_MAX) 296 ASMAtomicUoWriteU32(&mData.mNextContextID, 0); 297 /* Is the context ID already used? Try next ID ... */ 298 if (!callbackExists(uNewContextID)) 299 { 300 /* Callback with context ID was not found. This means 301 * we can use this context ID for our new callback we want 302 * to add below. */ 303 rc = VINF_SUCCESS; 304 break; 305 } 306 307 if (++uTries == UINT32_MAX) 308 break; /* Don't try too hard. */ 309 } 310 311 if (RT_SUCCESS(rc)) 312 { 313 /* Add callback with new context ID to our callback map. */ 314 mData.mCallbacks[uNewContextID] = theCallback; 315 Assert(mData.mCallbacks.size()); 316 317 /* Report back new context ID. */ 318 if (puContextID) 319 *puContextID = uNewContextID; 320 } 321 322 return rc; 323 } 324 325 bool GuestProcess::callbackExists(uint32_t uContextID) 326 { 327 AssertReturn(uContextID, false); 328 329 GuestCtrlCallbacks::const_iterator it = mData.mCallbacks.find(uContextID); 330 return (it == mData.mCallbacks.end()) ? false : true; 331 } 332 333 bool GuestProcess::isReady(void) 334 { 335 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 336 337 if (mData.mStatus == ProcessStatus_Started) 338 { 339 Assert(mData.mPID); /* PID must not be 0. */ 340 return true; 341 } 342 343 return false; 344 } 345 346 /** 347 * Appends environment variables to the environment block. 348 * 349 * Each var=value pair is separated by the null character ('\\0'). The whole 350 * block will be stored in one blob and disassembled on the guest side later to 351 * fit into the HGCM param structure. 352 * 353 * @returns VBox status code. 354 * 355 * @param pszEnvVar The environment variable=value to append to the 356 * environment block. 357 * @param ppvList This is actually a pointer to a char pointer 358 * variable which keeps track of the environment block 359 * that we're constructing. 360 * @param pcbList Pointer to the variable holding the current size of 361 * the environment block. (List is a misnomer, go 362 * ahead a be confused.) 363 * @param pcEnvVars Pointer to the variable holding count of variables 364 * stored in the environment block. 365 */ 366 int GuestProcess::prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnvVars) 367 { 368 int rc = VINF_SUCCESS; 369 uint32_t cchEnv = strlen(pszEnv); Assert(cchEnv >= 2); 370 if (*ppvList) 371 { 372 uint32_t cbNewLen = *pcbList + cchEnv + 1; /* Include zero termination. */ 373 char *pvTmp = (char *)RTMemRealloc(*ppvList, cbNewLen); 374 if (pvTmp == NULL) 375 rc = VERR_NO_MEMORY; 376 else 377 { 378 memcpy(pvTmp + *pcbList, pszEnv, cchEnv); 379 pvTmp[cbNewLen - 1] = '\0'; /* Add zero termination. */ 380 *ppvList = (void **)pvTmp; 381 } 382 } 383 else 384 { 385 char *pszTmp; 386 if (RTStrAPrintf(&pszTmp, "%s", pszEnv) >= 0) 387 { 388 *ppvList = (void **)pszTmp; 389 /* Reset counters. */ 390 *pcEnvVars = 0; 391 *pcbList = 0; 392 } 393 } 394 if (RT_SUCCESS(rc)) 395 { 396 *pcbList += cchEnv + 1; /* Include zero termination. */ 397 *pcEnvVars += 1; /* Increase env variable count. */ 398 } 399 return rc; 400 } 401 402 int GuestProcess::readData(ULONG aHandle, ULONG aSize, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData)) 403 { 404 LogFlowFuncEnter(); 405 406 LogFlowFuncLeave(); 407 return 0; 408 } 409 410 int GuestProcess::startProcess(void) 411 { 412 LogFlowFuncEnter(); 413 414 AssertReturn(!mData.mStarted, VERR_ALREADY_EXISTS); 415 416 int rc; 417 uint32_t uContextID; 418 419 { 420 /* Wait until the caller function (if kicked off by a thread) 421 * has returned and continue operation. */ 422 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 423 424 /* Create callback and add it to the map. */ 425 GuestCtrlCallback callbackStart; 426 rc = callbackStart.Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START); 427 if (RT_FAILURE(rc)) 428 return rc; 429 430 rc = callbackAdd(callbackStart, &uContextID); 431 Assert(uContextID); 432 } 433 434 if (RT_SUCCESS(rc)) 435 { 436 ComObjPtr<GuestSession> pSession(mData.mParent); 437 Assert(!pSession.isNull()); 438 439 const GuestCredentials &sessionCreds = pSession->getCredentials(); 440 441 /* Prepare arguments. */ 442 char *pszArgs = NULL; 443 size_t cArgs = mData.mProcess.mArguments.size(); 444 if (cArgs) 445 { 446 char **papszArgv = (char**)RTMemAlloc(sizeof(char*) * (cArgs + 1)); 447 AssertReturn(papszArgv, VERR_NO_MEMORY); 448 for (size_t i = 0; RT_SUCCESS(rc) && i < cArgs; i++) 449 rc = RTStrDupEx(&papszArgv[i], mData.mProcess.mArguments[i].c_str()); 450 papszArgv[cArgs] = NULL; 451 452 if (RT_SUCCESS(rc)) 453 rc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT); 454 } 455 uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */ 456 457 /* Prepare environment. */ 458 void *pvEnv = NULL; 459 size_t cEnv = mData.mProcess.mEnvironment.size(); 460 uint32_t cbEnv = 0; 461 if ( RT_SUCCESS(rc) 462 && cEnv) 463 { 464 uint32_t cEnvBuild = 0; 465 ProcessEnvironmentMap::const_iterator itEnv = mData.mProcess.mEnvironment.begin(); 466 for (; itEnv != mData.mProcess.mEnvironment.end() && RT_SUCCESS(rc); itEnv++) 467 { 468 char *pszEnv; 469 if (!RTStrAPrintf(&pszEnv, "%s=%s", itEnv->first, itEnv->second)) 470 break; 471 AssertPtr(pszEnv); 472 rc = prepareExecuteEnv(pszEnv, &pvEnv, &cbEnv, &cEnvBuild); 473 RTStrFree(pszEnv); 474 } 475 Assert(cEnv == cEnvBuild); 476 } 477 478 if (RT_SUCCESS(rc)) 479 { 480 /* Prepare HGCM call. */ 481 VBOXHGCMSVCPARM paParms[15]; 482 int i = 0; 483 paParms[i++].setUInt32(uContextID); 484 paParms[i++].setPointer((void*)mData.mProcess.mCommand.c_str(), 485 (uint32_t)mData.mProcess.mCommand.length() + 1); 486 paParms[i++].setUInt32(mData.mProcess.mFlags); 487 paParms[i++].setUInt32(mData.mProcess.mArguments.size()); 488 paParms[i++].setPointer((void*)pszArgs, cbArgs); 489 paParms[i++].setUInt32(mData.mProcess.mEnvironment.size()); 490 paParms[i++].setUInt32(cbEnv); 491 paParms[i++].setPointer((void*)pvEnv, cbEnv); 492 paParms[i++].setPointer((void*)sessionCreds.mUser.c_str(), (uint32_t)sessionCreds.mUser.length() + 1); 493 paParms[i++].setPointer((void*)sessionCreds.mPassword.c_str(), (uint32_t)sessionCreds.mPassword.length() + 1); 494 495 /* 496 * If the WaitForProcessStartOnly flag is set, we only want to define and wait for a timeout 497 * until the process was started - the process itself then gets an infinite timeout for execution. 498 * This is handy when we want to start a process inside a worker thread within a certain timeout 499 * but let the started process perform lengthly operations then. 500 */ 501 if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly) 502 paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */); 503 else 504 paParms[i++].setUInt32(mData.mProcess.mTimeoutMS); 505 506 const ComObjPtr<Console> pConsole(mData.mConsole); 507 Assert(!pConsole.isNull()); 508 509 VMMDev *pVMMDev = NULL; 510 { 511 /* Make sure mParent is valid, so set the read lock while using. 512 * Do not keep this lock while doing the actual call, because in the meanwhile 513 * another thread could request a write lock which would be a bad idea ... */ 514 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 515 516 /* Forward the information to the VMM device. */ 517 pVMMDev = pConsole->getVMMDev(); 518 } 519 520 LogFlowFunc(("hgcmHostCall numParms=%d, CID=%RU32\n", i, uContextID)); 521 rc = pVMMDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD, 522 i, paParms); 523 } 524 525 if (pvEnv) 526 RTMemFree(pvEnv); 527 if (pszArgs) 528 RTStrFree(pszArgs); 529 } 530 531 LogFlowFuncLeave(); 532 return rc; 533 } 534 535 DECLCALLBACK(int) GuestProcess::startProcessThread(RTTHREAD Thread, void *pvUser) 536 { 537 LogFlowFuncEnter(); 538 539 const ComObjPtr<GuestProcess> pProcess = static_cast<GuestProcess*>(pvUser); 540 Assert(!pProcess.isNull()); 541 542 int rc = pProcess->startProcess(); 543 544 LogFlowFuncLeave(); 545 return rc; 546 } 547 548 int GuestProcess::terminateProcess(void) 549 { 550 LogFlowFuncEnter(); 551 552 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 553 554 LogFlowFuncLeave(); 555 return 0; 556 } 557 558 int GuestProcess::waitFor(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitReason_T *aReason) 559 { 560 LogFlowFuncEnter(); 561 562 LogFlowFuncLeave(); 563 return 0; 564 } 565 566 int GuestProcess::writeData(ULONG aHandle, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten) 567 { 568 LogFlowFuncEnter(); 569 570 LogFlowFuncLeave(); 571 return 0; 163 572 } 164 573 … … 171 580 ReturnComNotImplemented(); 172 581 #else 173 AutoCaller autoCaller(this); 174 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 175 176 ReturnComNotImplemented(); 582 583 AutoCaller autoCaller(this); 584 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 585 586 int rc = readData(aHandle, aSize, aTimeoutMS, ComSafeArrayOutArg(aData)); 587 /** @todo Do setError() here. */ 588 return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 177 589 #endif /* VBOX_WITH_GUEST_CONTROL */ 178 590 } … … 186 598 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 187 599 188 ReturnComNotImplemented(); 600 int rc = terminateProcess(); 601 /** @todo Do setError() here. */ 602 return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 189 603 #endif /* VBOX_WITH_GUEST_CONTROL */ 190 604 } … … 198 612 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 199 613 200 ReturnComNotImplemented(); 614 int rc = waitFor(ComSafeArrayInArg(aFlags), aTimeoutMS, aReason); 615 /** @todo Do setError() here. */ 616 return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 201 617 #endif /* VBOX_WITH_GUEST_CONTROL */ 202 618 } … … 210 626 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 211 627 212 ReturnComNotImplemented(); 213 #endif /* VBOX_WITH_GUEST_CONTROL */ 214 } 215 628 int rc = writeData(aHandle, ComSafeArrayInArg(aData), aTimeoutMS, aWritten); 629 /** @todo Do setError() here. */ 630 return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 631 #endif /* VBOX_WITH_GUEST_CONTROL */ 632 } 633 -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r42117 r42160 53 53 ///////////////////////////////////////////////////////////////////////////// 54 54 55 int GuestSession::init(Guest *aGuest, 55 int GuestSession::init(Guest *aGuest, uint32_t aSessionID, 56 56 Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName) 57 57 { … … 63 63 64 64 mData.mParent = aGuest; 65 66 mData.mUser = aUser; 67 mData.mPassword = aPassword; 68 mData.mDomain = aDomain; 65 mData.mId = aSessionID; 66 67 mData.mCredentials.mUser = aUser; 68 mData.mCredentials.mPassword = aPassword; 69 mData.mCredentials.mDomain = aDomain; 69 70 mData.mName = aName; 70 71 … … 108 109 itProcs != mData.mProcesses.end(); ++itProcs) 109 110 { 110 (*itProcs)->uninit();111 (*itProcs).setNull();111 itProcs->second->uninit(); 112 itProcs->second.setNull(); 112 113 } 113 114 mData.mProcesses.clear(); … … 132 133 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 133 134 134 mData.m User.cloneTo(aUser);135 mData.mCredentials.mUser.cloneTo(aUser); 135 136 136 137 return S_OK; … … 150 151 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 151 152 152 mData.m Domain.cloneTo(aDomain);153 mData.mCredentials.mDomain.cloneTo(aDomain); 153 154 154 155 return S_OK; … … 228 229 ++it, ++s) 229 230 { 230 /** @todo */231 collection[s] = Bstr(it->first + "=" + it->second).raw(); 231 232 } 232 233 … … 306 307 if (pDirectory == (*itDirs)) 307 308 { 308 mData.mDirectories. remove((*itDirs));309 mData.mDirectories.erase(itDirs); 309 310 return VINF_SUCCESS; 310 311 } … … 323 324 if (pFile == (*itFiles)) 324 325 { 325 mData.mFiles. remove((*itFiles));326 mData.mFiles.erase(itFiles); 326 327 return VINF_SUCCESS; 327 328 } … … 331 332 } 332 333 334 const GuestCredentials& GuestSession::getCredentials(void) 335 { 336 return mData.mCredentials; 337 } 338 333 339 int GuestSession::processClose(ComObjPtr<GuestProcess> pProcess) 334 340 { … … 338 344 itProcs != mData.mProcesses.end(); ++itProcs) 339 345 { 340 if (pProcess == (*itProcs))346 if (pProcess == itProcs->second) 341 347 { 342 mData.mProcesses. remove((*itProcs));348 mData.mProcesses.erase(itProcs); 343 349 return VINF_SUCCESS; 344 350 } … … 348 354 } 349 355 350 int GuestSession::processCreateExInteral(const Utf8Str &aCommand, const StringsArray &aArguments, const StringsArray &aEnvironment, 351 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, 352 ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity), 353 IGuestProcess **aProcess) 356 int GuestSession::processCreateExInteral(GuestProcessInfo &aProcInfo, IGuestProcess **aProcess) 354 357 { 355 358 AssertPtrReturn(aProcess, VERR_INVALID_POINTER); 356 359 357 360 /* Validate flags. */ 358 com::SafeArray<ProcessCreateFlag_T> arrFlags(ComSafeArrayInArg(aFlags)); 359 for (size_t i = 0; i < arrFlags.size(); i++) 360 { 361 if (arrFlags[i] == ExecuteProcessFlag_None) 362 continue; 363 364 if ( !(arrFlags[i] & ExecuteProcessFlag_IgnoreOrphanedProcesses) 365 && !(arrFlags[i] & ExecuteProcessFlag_WaitForProcessStartOnly) 366 && !(arrFlags[i] & ExecuteProcessFlag_Hidden) 367 && !(arrFlags[i] & ExecuteProcessFlag_NoProfile)) 361 if (aProcInfo.mFlags) 362 { 363 if ( !(aProcInfo.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses) 364 && !(aProcInfo.mFlags & ProcessCreateFlag_WaitForProcessStartOnly) 365 && !(aProcInfo.mFlags & ProcessCreateFlag_Hidden) 366 && !(aProcInfo.mFlags & ProcessCreateFlag_NoProfile)) 368 367 { 369 368 return VERR_INVALID_PARAMETER; … … 373 372 /* Adjust timeout. If set to 0, we define 374 373 * an infinite timeout. */ 375 if (a TimeoutMS == 0)376 a TimeoutMS = UINT32_MAX;374 if (aProcInfo.mTimeoutMS == 0) 375 aProcInfo.mTimeoutMS = UINT32_MAX; 377 376 378 377 /** @tood Implement process priority + affinity. */ 379 378 380 int rc; 379 int rc = VERR_MAX_THRDS_REACHED; 380 381 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 382 383 /* Create a new (host-based) process ID and assign it. */ 384 uint32_t uNewProcessID = 0; 385 uint32_t uTries = 0; 386 387 for (;;) 388 { 389 /* Is the context ID already used? Try next ID ... */ 390 if (!processExists(uNewProcessID++)) 391 { 392 /* Callback with context ID was not found. This means 393 * we can use this context ID for our new callback we want 394 * to add below. */ 395 rc = VINF_SUCCESS; 396 break; 397 } 398 399 if (++uTries == UINT32_MAX) 400 break; /* Don't try too hard. */ 401 } 402 if (RT_FAILURE(rc)) throw rc; 403 381 404 ComObjPtr<GuestProcess> pGuestProcess; 382 405 try … … 386 409 if (FAILED(hr)) throw VERR_COM_UNEXPECTED; 387 410 388 rc = pGuestProcess->init(this, 389 aCommand, aArguments, aEnvironment, 390 ComSafeArrayInArg(aFlags), aTimeoutMS, 391 aPriority, ComSafeArrayInArg(aAffinity)); 411 rc = pGuestProcess->init(mData.mParent->getConsole() /* Console */, this /* Session */, 412 uNewProcessID, aProcInfo); 392 413 if (RT_FAILURE(rc)) throw rc; 393 414 394 mData.mProcesses .push_back(pGuestProcess);415 mData.mProcesses[uNewProcessID] = pGuestProcess; 395 416 396 417 /* Return guest session to the caller. */ … … 404 425 405 426 return rc; 406 407 #if 0 408 int rc = VINF_SUCCESS; 409 410 char **papszArgv = NULL; 411 try 412 { 413 /* Prepare arguments. */ 414 uint32_t uNumArgs = 0; 415 if (aArguments) 416 { 417 com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments)); 418 uNumArgs = args.size(); 419 papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1)); 420 AssertReturn(papszArgv, VERR_NO_MEMORY); 421 for (unsigned i = 0; RT_SUCCESS(rc) && i < uNumArgs; i++) 422 rc = RTUtf16ToUtf8(args[i], &papszArgv[i]); 423 papszArgv[uNumArgs] = NULL; 424 425 if (RT_FAILURE(rc)) 426 return rc; 427 } 428 429 char *pszArgs = NULL; 430 if (uNumArgs) 431 { 432 rc = RTGetOptArgvToString(&pszArgs, papszArgv, RTGETOPTARGV_CNV_QUOTE_MS_CRT); 433 if (RT_FAILURE(rc)) throw rc; 434 } 435 436 /* Get number of arguments. */ 437 uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */ 438 439 /* Prepare environment. */ 440 void *pvEnv = NULL; 441 uint32_t uNumEnv = 0; 442 uint32_t cbEnv = 0; 443 if (aEnvironment) 444 { 445 com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment)); 446 447 for (unsigned i = 0; RT_SUCCESS(rc) && i < env.size(); i++) 448 rc = prepareExecuteEnv(Utf8Str(env[i]).c_str(), &pvEnv, &cbEnv, &uNumEnv); 449 } 450 } 451 catch (int eRc) 452 { 453 454 455 rc = exRc; 456 } 457 458 for (unsigned i = 0; i < uNumArgs; i++) 459 RTMemFree(papszArgv[i]); 460 RTMemFree(papszArgv); 461 #endif 462 463 return rc; 427 } 428 429 inline bool GuestSession::processExists(uint32_t uProcessID) 430 { 431 AssertReturn(uProcessID, false); 432 433 SessionProcesses::const_iterator itProcesses = mData.mProcesses.find(uProcessID); 434 return (itProcesses == mData.mProcesses.end()) ? false : true; 464 435 } 465 436 … … 760 731 ReturnComNotImplemented(); 761 732 #else 762 AutoCaller autoCaller(this); 763 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 764 765 CheckComArgOutPointerValid(aProcess); 766 767 com::SafeArray<LONG> affinity; /** @todo Process affinity, not used yet. */ 768 769 com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments)); 770 StringsArray argumentsUtf8(arguments.size()); 771 for (size_t i = 0; i < arguments.size(); i++) 772 argumentsUtf8[i] = Utf8Str(Bstr(arguments[i])); 773 774 com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment)); 775 StringsArray environmentUtf8(environment.size()); 776 for (size_t i = 0; i < environment.size(); i++) 777 environmentUtf8[i] = Utf8Str(Bstr(environment[i])); 778 779 int rc = processCreateExInteral(Utf8Str(aCommand), argumentsUtf8, environmentUtf8, 780 ComSafeArrayInArg(aFlags), aTimeoutMS, 781 ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess); 782 return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 733 734 com::SafeArray<LONG> affinity; 735 736 return ProcessCreateEx(aCommand, ComSafeArrayInArg(aArguments), ComSafeArrayInArg(aEnvironment), 737 ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess); 783 738 #endif /* VBOX_WITH_GUEST_CONTROL */ 784 739 } … … 797 752 CheckComArgOutPointerValid(aProcess); 798 753 754 GuestProcessInfo procInfo; 755 756 procInfo.mCommand = Utf8Str(aCommand); 757 799 758 com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments)); 800 StringsArray argumentsUtf8(arguments.size());759 procInfo.mArguments.reserve(arguments.size()); 801 760 for (size_t i = 0; i < arguments.size(); i++) 802 argumentsUtf8[i] = Utf8Str(Bstr(arguments[i]));761 procInfo.mArguments[i] = Utf8Str(Bstr(arguments[i])); 803 762 804 763 com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment)); 805 StringsArray environmentUtf8(environment.size());806 764 for (size_t i = 0; i < environment.size(); i++) 807 environmentUtf8[i] = Utf8Str(Bstr(environment[i])); 808 809 int rc = processCreateExInteral(Utf8Str(aCommand), argumentsUtf8, environmentUtf8, 810 ComSafeArrayInArg(aFlags), aTimeoutMS, 811 aPriority, ComSafeArrayInArg(aAffinity), aProcess); 765 { 766 Utf8Str strEnv = Bstr(environment[i]); 767 RTCList<RTCString> listPair = strEnv.split("=", RTCString::KeepEmptyParts); 768 size_t p = 0; 769 while(p < listPair.size()) 770 { 771 Utf8Str strKey = listPair.at(p++); 772 if (strKey.isEmpty()) /* Skip pairs with empty keys (e.g. "=FOO"). */ 773 { 774 p++; 775 continue; 776 } 777 Utf8Str strValue; 778 if (p < listPair.size()) 779 strValue = listPair.at(p++); 780 procInfo.mEnvironment[strKey] = strValue; 781 } 782 } 783 784 com::SafeArray<ProcessCreateFlag_T> flags(ComSafeArrayInArg(aFlags)); 785 for (size_t i = 0; i < flags.size(); i++) 786 procInfo.mFlags |= flags[i]; 787 788 procInfo.mTimeoutMS = aTimeoutMS; 789 790 com::SafeArray<LONG> affinity(ComSafeArrayInArg(aAffinity)); 791 procInfo.mAffinity.reserve(affinity.size()); 792 for (size_t i = 0; i < affinity.size(); i++) 793 procInfo.mAffinity[i] = affinity[i]; /** @todo Really necessary? Later. */ 794 795 procInfo.mPriority = aPriority; 796 797 int rc = processCreateExInteral(procInfo, aProcess); 812 798 return RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR; 813 799 #endif /* VBOX_WITH_GUEST_CONTROL */ -
trunk/src/VBox/Main/testcase/Makefile.kmk
r41528 r42160 151 151 # 152 152 tstGuestCtrlParseBuffer_TEMPLATE = VBOXMAINCLIENTEXE 153 tstGuestCtrlParseBuffer_DEFS += VBOX_WITH_HGCM VBOX_WITH_GUEST_CONTROL 153 154 tstGuestCtrlParseBuffer_SOURCES = \ 154 155 tstGuestCtrlParseBuffer.cpp \ 155 ../src-client/GuestCtrl IO.cpp156 ../src-client/GuestCtrlPrivate.cpp 156 157 tstGuestCtrlParseBuffer_INCS = ../include 157 158 ifeq ($(KBUILD_TARGET),win) ## @todo just add this to the template.
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器