VirtualBox

Changeset 104178 in vbox for trunk/src


Ignore:
Timestamp:
Apr 5, 2024 12:23:48 PM (10 months ago)
Author:
vboxsync
Message:

Guest Control:

  • Factored out most of the guest process stream handling of GuestToolboxStream (deprecated) into a new generic class GuestProcessOutputStream. That way we can make use of most of that code for other, non-toolbox related functionality.
  • Factoredd out most of the guest process wrapping functionality from GuestProcessToolbox into a new generic class GuestProcessWrapper. Ditto (see above).
  • Make more use of VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT to compile a lot less code if not defined. Toolbox handling is required for supporting older Guest Additions (< 7.1) though (so enabled by default).
Location:
trunk/src/VBox/Main
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r104003 r104178  
    968968};
    969969
     970/**
     971 * Generic class for handling a guest process output (i.e. stdout / stderr) stream.
     972 */
     973class GuestProcessOutputStream
     974{
     975public:
     976
     977    GuestProcessOutputStream();
     978
     979    virtual ~GuestProcessOutputStream();
     980
     981public:
     982
     983    int AddData(const BYTE *pbData, size_t cbData);
     984
     985    void Destroy();
     986
     987#ifdef DEBUG
     988    void Dump(const char *pszFile);
     989#endif
     990
     991    size_t GetOffset(void) const { return m_offBuf; }
     992
     993    size_t GetSize(void) const { return m_cbUsed; }
     994
     995    const BYTE *GetData(void) const { return m_pbBuffer; }
     996
     997protected:
     998
     999    /** Maximum allowed size the stream buffer can grow to.
     1000     *  Defaults to 32 MB. */
     1001    size_t m_cbMax;
     1002    /** Currently allocated size of internal stream buffer. */
     1003    size_t m_cbAllocated;
     1004    /** Currently used size at m_offBuffer. */
     1005    size_t m_cbUsed;
     1006    /** Current byte offset within the internal stream buffer. */
     1007    size_t m_offBuf;
     1008    /** Internal stream buffer. */
     1009    BYTE  *m_pbBuffer;
     1010};
    9701011
    9711012/**
     
    10101051 *
    10111052 * Only used for the busybox-like toolbox commands within VBoxService.
     1053 *
    10121054 * Deprecated, do not use anymore.
    10131055 */
     
    10821124 * Deprecated, do not use anymore.
    10831125 */
    1084 class GuestToolboxStream
     1126class GuestToolboxStream : public GuestProcessOutputStream
    10851127{
    10861128
     
    10931135public:
    10941136
    1095     int AddData(const BYTE *pbData, size_t cbData);
    1096 
    1097     void Destroy();
    1098 
    1099 #ifdef DEBUG
    1100     void Dump(const char *pszFile);
    1101 #endif
    1102 
    1103     size_t GetOffset(void) const { return m_offBuf; }
    1104 
    1105     size_t GetSize(void) const { return m_cbUsed; }
    1106 
    11071137    size_t GetBlocks(void) const { return m_cBlocks; }
    11081138
     
    11111141protected:
    11121142
    1113     /** Maximum allowed size the stream buffer can grow to.
    1114      *  Defaults to 32 MB. */
    1115     size_t m_cbMax;
    1116     /** Currently allocated size of internal stream buffer. */
    1117     size_t m_cbAllocated;
    1118     /** Currently used size at m_offBuffer. */
    1119     size_t m_cbUsed;
    1120     /** Current byte offset within the internal stream buffer. */
    1121     size_t m_offBuf;
    1122     /** Internal stream buffer. */
    1123     BYTE  *m_pbBuffer;
    11241143    /** How many completed stream blocks already were processed. */
    11251144    size_t m_cBlocks;
  • trunk/src/VBox/Main/include/GuestProcessImpl.h

    r98614 r104178  
    217217
    218218/**
     219 * Wrapper class for running guest processes.
     220 */
     221class GuestProcessWrapper
     222{
     223public:
     224    DECLARE_TRANSLATE_METHODS(GuestProcessWrapper)
     225
     226    GuestProcessWrapper(void);
     227
     228    virtual ~GuestProcessWrapper(void);
     229
     230public:
     231
     232    int init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pvrcGuest);
     233
     234    void uninit(void);
     235
     236    /** Returns the stdout output from the guest process. */
     237    GuestProcessOutputStream &getStdOut(void) { return mStdOut; }
     238
     239    /** Returns the stderr output from the guest proces. */
     240    GuestProcessOutputStream &getStdErr(void) { return mStdErr; }
     241
     242    bool isRunning(void);
     243
     244    bool isTerminatedOk(void);
     245
     246    int getTerminationStatus(int32_t *piExitCode = NULL);
     247
     248    int terminate(uint32_t uTimeoutMS, int *pvrcGuest);
     249
     250protected:
     251
     252    /** Pointer to session this toolbox object is bound to. */
     253    ComObjPtr<GuestSession>     pSession;
     254    /** Pointer to process object this object is bound to. */
     255    ComObjPtr<GuestProcess>     pProcess;
     256    /** The process startup info. */
     257    GuestProcessStartupInfo     mStartupInfo;
     258    /** Stream object for handling stdout data. */
     259    GuestProcessOutputStream    mStdOut;
     260    /** Stream object for handling stderr data. */
     261    GuestProcessOutputStream    mStdErr;
     262};
     263
     264#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     265/**
    219266 * Internal class for handling the BusyBox-like tools built into VBoxService
    220267 * on the guest side. It's also called the VBoxService Toolbox (tm).
     
    228275 * Note! When implementing new functionality / commands, do *not* use this approach anymore!
    229276 *       This class has to be kept to guarantee backwards-compatibility.
    230  */
    231 class GuestProcessToolbox
     277 *
     278 * Deprecated, do not use anymore.
     279 */
     280class GuestProcessToolbox : public GuestProcessWrapper
    232281{
    233282public:
    234     DECLARE_TRANSLATE_METHODS(GuestProcessTool)
     283    DECLARE_TRANSLATE_METHODS(GuestProcessToolbox)
    235284
    236285    GuestProcessToolbox(void);
     
    240289public:
    241290
    242     int init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo, bool fAsync, int *pvrcGuest);
    243 
    244     void uninit(void);
     291    int wait(uint32_t fToolWaitFlags, int *pvrcGuest);
     292
     293    int waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *strmBlockOut, int *pvrcGuest);
    245294
    246295    int getCurrentBlock(uint32_t uHandle, GuestToolboxStreamBlock &strmBlock);
     
    253302    /** Returns the stderr output from the guest process tool. */
    254303    GuestToolboxStream &getStdErr(void) { return mStdErr; }
    255 
    256     int wait(uint32_t fToolWaitFlags, int *pvrcGuest);
    257 
    258     int waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *pStreamBlock, int *pvrcGuest);
    259 
    260     bool isRunning(void);
    261 
    262     bool isTerminatedOk(void);
    263 
    264     int getTerminationStatus(int32_t *piExitCode = NULL);
    265 
    266     int terminate(uint32_t uTimeoutMS, int *pvrcGuest);
    267304
    268305public:
     
    282319     * @{ */
    283320    static int exitCodeToRc(const GuestProcessStartupInfo &startupInfo, int32_t iExitCode);
    284 
    285321    static int exitCodeToRc(const char *pszTool, int32_t iExitCode);
    286322    /** @}  */
     
    293329protected:
    294330
    295     /** Pointer to session this toolbox object is bound to. */
    296     ComObjPtr<GuestSession>     pSession;
    297     /** Pointer to process object this toolbox object is bound to. */
    298     ComObjPtr<GuestProcess>     pProcess;
    299     /** The toolbox' startup info. */
    300     GuestProcessStartupInfo     mStartupInfo;
    301331    /** Stream object for handling the toolbox' stdout data. */
    302332    GuestToolboxStream          mStdOut;
     
    304334    GuestToolboxStream          mStdErr;
    305335};
     336#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    306337
    307338#endif /* !MAIN_INCLUDED_GuestProcessImpl_h */
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r102654 r104178  
    363363    /** @}  */
    364364
     365#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    365366    /** @name Public internal methods for supporting older Guest Additions via
    366      *        VBoxService' built-in toolbox (< 7.1).
     367     *        VBoxService' built-in toolbox (< 7.1). Deprecated, do not use anymore.
    367368     * @{  */
    368369    int                     i_directoryCreateViaToolbox(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pvrcGuest);
     
    372373    int                     i_fsObjQueryInfoViaToolbox(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pvrcGuest);
    373374    /** @}  */
     375#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    374376
    375377public:
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r99393 r104178  
    530530///////////////////////////////////////////////////////////////////////////////
    531531
    532 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    533 /** @todo *NOT* thread safe yet! */
    534 /** @todo Add exception handling for STL stuff! */
    535 
    536 GuestToolboxStreamBlock::GuestToolboxStreamBlock(void)
    537     : m_fComplete(false) { }
    538 
    539 GuestToolboxStreamBlock::~GuestToolboxStreamBlock()
    540 {
    541     Clear();
    542 }
    543 
    544 /**
    545  * Clears (destroys) the currently stored stream pairs.
    546  */
    547 void GuestToolboxStreamBlock::Clear(void)
    548 {
    549     m_fComplete = false;
    550     m_mapPairs.clear();
    551 }
    552 
    553 #ifdef DEBUG
    554 /**
    555  * Dumps the currently stored stream pairs to the (debug) log.
    556  */
    557 void GuestToolboxStreamBlock::DumpToLog(void) const
    558 {
    559     LogFlowFunc(("Dumping contents of stream block=0x%p (%ld items, fComplete=%RTbool):\n",
    560                  this, m_mapPairs.size(), m_fComplete));
    561 
    562     for (GuestCtrlStreamPairMapIterConst it = m_mapPairs.begin();
    563          it != m_mapPairs.end(); ++it)
    564     {
    565         LogFlowFunc(("\t%s=%s\n", it->first.c_str(), it->second.mValue.c_str()));
    566     }
    567 }
    568 #endif
    569 
    570 /**
    571  * Returns a 64-bit signed integer of a specified key.
    572  *
    573  * @return VBox status code. VERR_NOT_FOUND if key was not found.
    574  * @param  pszKey               Name of key to get the value for.
    575  * @param  piVal                Pointer to value to return.
    576  */
    577 int GuestToolboxStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal) const
    578 {
    579     AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
    580     AssertPtrReturn(piVal, VERR_INVALID_POINTER);
    581     const char *pszValue = GetString(pszKey);
    582     if (pszValue)
    583     {
    584         *piVal = RTStrToInt64(pszValue);
    585         return VINF_SUCCESS;
    586     }
    587     return VERR_NOT_FOUND;
    588 }
    589 
    590 /**
    591  * Returns a 64-bit integer of a specified key.
    592  *
    593  * @return  int64_t             Value to return, 0 if not found / on failure.
    594  * @param   pszKey              Name of key to get the value for.
    595  */
    596 int64_t GuestToolboxStreamBlock::GetInt64(const char *pszKey) const
    597 {
    598     int64_t iVal;
    599     if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
    600         return iVal;
    601     return 0;
    602 }
    603 
    604 /**
    605  * Returns the current number of stream pairs.
    606  *
    607  * @return  uint32_t            Current number of stream pairs.
    608  */
    609 size_t GuestToolboxStreamBlock::GetCount(void) const
    610 {
    611     return m_mapPairs.size();
    612 }
    613 
    614 /**
    615  * Gets the return code (name = "rc") of this stream block.
    616  *
    617  * @return  VBox status code.
    618  * @retval  VERR_NOT_FOUND if the return code string ("rc") was not found.
    619  * @param   fSucceedIfNotFound  When set to @c true, this reports back VINF_SUCCESS when the key ("rc") is not found.
    620  *                              This can happen with some (older) IPRT-provided tools such as RTPathRmCmd(), which only outputs
    621  *                              rc on failure but not on success. Defaults to @c false.
    622  */
    623 int GuestToolboxStreamBlock::GetVrc(bool fSucceedIfNotFound /* = false */) const
    624 {
    625     const char *pszValue = GetString("rc");
    626     if (pszValue)
    627         return RTStrToInt16(pszValue);
    628     if (fSucceedIfNotFound)
    629         return VINF_SUCCESS;
    630     /** @todo We probably should have a dedicated error for that, VERR_GSTCTL_GUEST_TOOLBOX_whatever. */
    631     return VERR_NOT_FOUND;
    632 }
    633 
    634 /**
    635  * Returns a string value of a specified key.
    636  *
    637  * @return  uint32_t            Pointer to string to return, NULL if not found / on failure.
    638  * @param   pszKey              Name of key to get the value for.
    639  */
    640 const char *GuestToolboxStreamBlock::GetString(const char *pszKey) const
    641 {
    642     AssertPtrReturn(pszKey, NULL);
    643 
    644     try
    645     {
    646         GuestCtrlStreamPairMapIterConst itPairs = m_mapPairs.find(pszKey);
    647         if (itPairs != m_mapPairs.end())
    648             return itPairs->second.mValue.c_str();
    649     }
    650     catch (const std::exception &ex)
    651     {
    652         RT_NOREF(ex);
    653     }
    654     return NULL;
    655 }
    656 
    657 /**
    658  * Returns a 32-bit unsigned integer of a specified key.
    659  *
    660  * @return  VBox status code. VERR_NOT_FOUND if key was not found.
    661  * @param   pszKey              Name of key to get the value for.
    662  * @param   puVal               Pointer to value to return.
    663  */
    664 int GuestToolboxStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) const
    665 {
    666     const char *pszValue = GetString(pszKey);
    667     if (pszValue)
    668     {
    669         *puVal = RTStrToUInt32(pszValue);
    670         return VINF_SUCCESS;
    671     }
    672     return VERR_NOT_FOUND;
    673 }
    674 
    675 /**
    676  * Returns a 32-bit signed integer of a specified key.
    677  *
    678  * @returns 32-bit signed value
    679  * @param   pszKey              Name of key to get the value for.
    680  * @param   iDefault            The default to return on error if not found.
    681  */
    682 int32_t GuestToolboxStreamBlock::GetInt32(const char *pszKey, int32_t iDefault) const
    683 {
    684     const char *pszValue = GetString(pszKey);
    685     if (pszValue)
    686     {
    687         int32_t iRet;
    688         int vrc = RTStrToInt32Full(pszValue, 0, &iRet);
    689         if (RT_SUCCESS(vrc))
    690             return iRet;
    691         ASSERT_GUEST_MSG_FAILED(("%s=%s\n", pszKey, pszValue));
    692     }
    693     return iDefault;
    694 }
    695 
    696 /**
    697  * Returns a 32-bit unsigned integer of a specified key.
    698  *
    699  * @return  uint32_t            Value to return, 0 if not found / on failure.
    700  * @param   pszKey              Name of key to get the value for.
    701  * @param   uDefault            The default value to return.
    702  */
    703 uint32_t GuestToolboxStreamBlock::GetUInt32(const char *pszKey, uint32_t uDefault /*= 0*/) const
    704 {
    705     uint32_t uVal;
    706     if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
    707         return uVal;
    708     return uDefault;
    709 }
    710 
    711 /**
    712  * Sets a value to a key or deletes a key by setting a NULL value. Extended version.
    713  *
    714  * @return  VBox status code.
    715  * @param   pszKey              Key name to process.
    716  * @param   cwcKey              Maximum characters of \a pszKey to process.
    717  * @param   pszValue            Value to set. Set NULL for deleting the key.
    718  * @param   cwcValue            Maximum characters of \a pszValue to process.
    719  * @param   fOverwrite          Whether a key can be overwritten with a new value if it already exists. Will assert otherwise.
    720  */
    721 int GuestToolboxStreamBlock::SetValueEx(const char *pszKey, size_t cwcKey, const char *pszValue, size_t cwcValue,
    722                                         bool fOverwrite /* = false */)
    723 {
    724     AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
    725     AssertReturn(cwcKey, VERR_INVALID_PARAMETER);
    726 
    727     int vrc = VINF_SUCCESS;
    728     try
    729     {
    730         Utf8Str const strKey(pszKey, cwcKey);
    731 
    732         /* Take a shortcut and prevent crashes on some funny versions
    733          * of STL if map is empty initially. */
    734         if (!m_mapPairs.empty())
    735         {
    736             GuestCtrlStreamPairMapIter it = m_mapPairs.find(strKey);
    737             if (it != m_mapPairs.end())
    738             {
    739                 if (pszValue == NULL)
    740                     m_mapPairs.erase(it);
    741                 else if (!fOverwrite)
    742                     AssertMsgFailedReturn(("Key '%*s' already exists! Value is '%s'\n", cwcKey, pszKey, m_mapPairs[strKey].mValue.c_str()),
    743                                           VERR_ALREADY_EXISTS);
    744             }
    745         }
    746 
    747         if (pszValue)
    748         {
    749             GuestToolboxStreamValue val(pszValue, cwcValue);
    750             Log3Func(("strKey='%s', strValue='%s'\n", strKey.c_str(), val.mValue.c_str()));
    751             m_mapPairs[strKey] = val;
    752         }
    753     }
    754     catch (const std::exception &)
    755     {
    756         /** @todo set vrc?   */
    757     }
    758     return vrc;
    759 }
    760 
    761 /**
    762  * Sets a value to a key or deletes a key by setting a NULL value.
    763  *
    764  * @return  VBox status code.
    765  * @param   pszKey              Key name to process.
    766  * @param   pszValue            Value to set. Set NULL for deleting the key.
    767  */
    768 int GuestToolboxStreamBlock::SetValue(const char *pszKey, const char *pszValue)
    769 {
    770     return SetValueEx(pszKey, RTSTR_MAX, pszValue, RTSTR_MAX);
    771 }
    772 
    773 ///////////////////////////////////////////////////////////////////////////////
    774 
    775 GuestToolboxStream::GuestToolboxStream(void)
     532GuestProcessOutputStream::GuestProcessOutputStream(void)
    776533    : m_cbMax(_32M)
    777534    , m_cbAllocated(0)
    778535    , m_cbUsed(0)
    779536    , m_offBuf(0)
    780     , m_pbBuffer(NULL)
    781     , m_cBlocks(0) { }
    782 
    783 GuestToolboxStream::~GuestToolboxStream(void)
     537    , m_pbBuffer(NULL) { }
     538
     539GuestProcessOutputStream::~GuestProcessOutputStream(void)
    784540{
    785541    Destroy();
     
    794550 * @param   cbData              Size (in bytes) of data to add.
    795551 */
    796 int GuestToolboxStream::AddData(const BYTE *pbData, size_t cbData)
     552int GuestProcessOutputStream::AddData(const BYTE *pbData, size_t cbData)
    797553{
    798554    AssertPtrReturn(pbData, VERR_INVALID_POINTER);
     
    865621 * Destroys the internal data buffer.
    866622 */
    867 void GuestToolboxStream::Destroy(void)
     623void GuestProcessOutputStream::Destroy(void)
    868624{
    869625    if (m_pbBuffer)
     
    876632    m_cbUsed = 0;
    877633    m_offBuf = 0;
    878     m_cBlocks = 0;
    879634}
    880635
     
    886641 * @param   pszFile             Absolute path to host file to dump the output to.
    887642 */
    888 void GuestToolboxStream::Dump(const char *pszFile)
     643void GuestProcessOutputStream::Dump(const char *pszFile)
    889644{
    890645    LogFlowFunc(("Dumping contents of stream=0x%p (cbAlloc=%u, cbSize=%u, cbOff=%u) to %s\n",
     
    900655}
    901656#endif /* DEBUG */
     657
     658///////////////////////////////////////////////////////////////////////////////
     659
     660#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     661/** @todo *NOT* thread safe yet! */
     662/** @todo Add exception handling for STL stuff! */
     663
     664GuestToolboxStreamBlock::GuestToolboxStreamBlock(void)
     665    : m_fComplete(false) { }
     666
     667GuestToolboxStreamBlock::~GuestToolboxStreamBlock()
     668{
     669    Clear();
     670}
     671
     672/**
     673 * Clears (destroys) the currently stored stream pairs.
     674 */
     675void GuestToolboxStreamBlock::Clear(void)
     676{
     677    m_fComplete = false;
     678    m_mapPairs.clear();
     679}
     680
     681#ifdef DEBUG
     682/**
     683 * Dumps the currently stored stream pairs to the (debug) log.
     684 */
     685void GuestToolboxStreamBlock::DumpToLog(void) const
     686{
     687    LogFlowFunc(("Dumping contents of stream block=0x%p (%ld items, fComplete=%RTbool):\n",
     688                 this, m_mapPairs.size(), m_fComplete));
     689
     690    for (GuestCtrlStreamPairMapIterConst it = m_mapPairs.begin();
     691         it != m_mapPairs.end(); ++it)
     692    {
     693        LogFlowFunc(("\t%s=%s\n", it->first.c_str(), it->second.mValue.c_str()));
     694    }
     695}
     696#endif
     697
     698/**
     699 * Returns a 64-bit signed integer of a specified key.
     700 *
     701 * @return VBox status code. VERR_NOT_FOUND if key was not found.
     702 * @param  pszKey               Name of key to get the value for.
     703 * @param  piVal                Pointer to value to return.
     704 */
     705int GuestToolboxStreamBlock::GetInt64Ex(const char *pszKey, int64_t *piVal) const
     706{
     707    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
     708    AssertPtrReturn(piVal, VERR_INVALID_POINTER);
     709    const char *pszValue = GetString(pszKey);
     710    if (pszValue)
     711    {
     712        *piVal = RTStrToInt64(pszValue);
     713        return VINF_SUCCESS;
     714    }
     715    return VERR_NOT_FOUND;
     716}
     717
     718/**
     719 * Returns a 64-bit integer of a specified key.
     720 *
     721 * @return  int64_t             Value to return, 0 if not found / on failure.
     722 * @param   pszKey              Name of key to get the value for.
     723 */
     724int64_t GuestToolboxStreamBlock::GetInt64(const char *pszKey) const
     725{
     726    int64_t iVal;
     727    if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
     728        return iVal;
     729    return 0;
     730}
     731
     732/**
     733 * Returns the current number of stream pairs.
     734 *
     735 * @return  uint32_t            Current number of stream pairs.
     736 */
     737size_t GuestToolboxStreamBlock::GetCount(void) const
     738{
     739    return m_mapPairs.size();
     740}
     741
     742/**
     743 * Gets the return code (name = "rc") of this stream block.
     744 *
     745 * @return  VBox status code.
     746 * @retval  VERR_NOT_FOUND if the return code string ("rc") was not found.
     747 * @param   fSucceedIfNotFound  When set to @c true, this reports back VINF_SUCCESS when the key ("rc") is not found.
     748 *                              This can happen with some (older) IPRT-provided tools such as RTPathRmCmd(), which only outputs
     749 *                              rc on failure but not on success. Defaults to @c false.
     750 */
     751int GuestToolboxStreamBlock::GetVrc(bool fSucceedIfNotFound /* = false */) const
     752{
     753    const char *pszValue = GetString("rc");
     754    if (pszValue)
     755        return RTStrToInt16(pszValue);
     756    if (fSucceedIfNotFound)
     757        return VINF_SUCCESS;
     758    /** @todo We probably should have a dedicated error for that, VERR_GSTCTL_GUEST_TOOLBOX_whatever. */
     759    return VERR_NOT_FOUND;
     760}
     761
     762/**
     763 * Returns a string value of a specified key.
     764 *
     765 * @return  uint32_t            Pointer to string to return, NULL if not found / on failure.
     766 * @param   pszKey              Name of key to get the value for.
     767 */
     768const char *GuestToolboxStreamBlock::GetString(const char *pszKey) const
     769{
     770    AssertPtrReturn(pszKey, NULL);
     771
     772    try
     773    {
     774        GuestCtrlStreamPairMapIterConst itPairs = m_mapPairs.find(pszKey);
     775        if (itPairs != m_mapPairs.end())
     776            return itPairs->second.mValue.c_str();
     777    }
     778    catch (const std::exception &ex)
     779    {
     780        RT_NOREF(ex);
     781    }
     782    return NULL;
     783}
     784
     785/**
     786 * Returns a 32-bit unsigned integer of a specified key.
     787 *
     788 * @return  VBox status code. VERR_NOT_FOUND if key was not found.
     789 * @param   pszKey              Name of key to get the value for.
     790 * @param   puVal               Pointer to value to return.
     791 */
     792int GuestToolboxStreamBlock::GetUInt32Ex(const char *pszKey, uint32_t *puVal) const
     793{
     794    const char *pszValue = GetString(pszKey);
     795    if (pszValue)
     796    {
     797        *puVal = RTStrToUInt32(pszValue);
     798        return VINF_SUCCESS;
     799    }
     800    return VERR_NOT_FOUND;
     801}
     802
     803/**
     804 * Returns a 32-bit signed integer of a specified key.
     805 *
     806 * @returns 32-bit signed value
     807 * @param   pszKey              Name of key to get the value for.
     808 * @param   iDefault            The default to return on error if not found.
     809 */
     810int32_t GuestToolboxStreamBlock::GetInt32(const char *pszKey, int32_t iDefault) const
     811{
     812    const char *pszValue = GetString(pszKey);
     813    if (pszValue)
     814    {
     815        int32_t iRet;
     816        int vrc = RTStrToInt32Full(pszValue, 0, &iRet);
     817        if (RT_SUCCESS(vrc))
     818            return iRet;
     819        ASSERT_GUEST_MSG_FAILED(("%s=%s\n", pszKey, pszValue));
     820    }
     821    return iDefault;
     822}
     823
     824/**
     825 * Returns a 32-bit unsigned integer of a specified key.
     826 *
     827 * @return  uint32_t            Value to return, 0 if not found / on failure.
     828 * @param   pszKey              Name of key to get the value for.
     829 * @param   uDefault            The default value to return.
     830 */
     831uint32_t GuestToolboxStreamBlock::GetUInt32(const char *pszKey, uint32_t uDefault /*= 0*/) const
     832{
     833    uint32_t uVal;
     834    if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
     835        return uVal;
     836    return uDefault;
     837}
     838
     839/**
     840 * Sets a value to a key or deletes a key by setting a NULL value. Extended version.
     841 *
     842 * @return  VBox status code.
     843 * @param   pszKey              Key name to process.
     844 * @param   cwcKey              Maximum characters of \a pszKey to process.
     845 * @param   pszValue            Value to set. Set NULL for deleting the key.
     846 * @param   cwcValue            Maximum characters of \a pszValue to process.
     847 * @param   fOverwrite          Whether a key can be overwritten with a new value if it already exists. Will assert otherwise.
     848 */
     849int GuestToolboxStreamBlock::SetValueEx(const char *pszKey, size_t cwcKey, const char *pszValue, size_t cwcValue,
     850                                        bool fOverwrite /* = false */)
     851{
     852    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
     853    AssertReturn(cwcKey, VERR_INVALID_PARAMETER);
     854
     855    int vrc = VINF_SUCCESS;
     856    try
     857    {
     858        Utf8Str const strKey(pszKey, cwcKey);
     859
     860        /* Take a shortcut and prevent crashes on some funny versions
     861         * of STL if map is empty initially. */
     862        if (!m_mapPairs.empty())
     863        {
     864            GuestCtrlStreamPairMapIter it = m_mapPairs.find(strKey);
     865            if (it != m_mapPairs.end())
     866            {
     867                if (pszValue == NULL)
     868                    m_mapPairs.erase(it);
     869                else if (!fOverwrite)
     870                    AssertMsgFailedReturn(("Key '%*s' already exists! Value is '%s'\n", cwcKey, pszKey, m_mapPairs[strKey].mValue.c_str()),
     871                                          VERR_ALREADY_EXISTS);
     872            }
     873        }
     874
     875        if (pszValue)
     876        {
     877            GuestToolboxStreamValue val(pszValue, cwcValue);
     878            Log3Func(("strKey='%s', strValue='%s'\n", strKey.c_str(), val.mValue.c_str()));
     879            m_mapPairs[strKey] = val;
     880        }
     881    }
     882    catch (const std::exception &)
     883    {
     884        /** @todo set vrc?   */
     885    }
     886    return vrc;
     887}
     888
     889/**
     890 * Sets a value to a key or deletes a key by setting a NULL value.
     891 *
     892 * @return  VBox status code.
     893 * @param   pszKey              Key name to process.
     894 * @param   pszValue            Value to set. Set NULL for deleting the key.
     895 */
     896int GuestToolboxStreamBlock::SetValue(const char *pszKey, const char *pszValue)
     897{
     898    return SetValueEx(pszKey, RTSTR_MAX, pszValue, RTSTR_MAX);
     899}
     900
     901///////////////////////////////////////////////////////////////////////////////
     902
     903GuestToolboxStream::GuestToolboxStream(void)
     904    : m_cBlocks(0)
     905{
     906}
     907
     908GuestToolboxStream::~GuestToolboxStream(void)
     909{
     910}
    902911
    903912/**
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r104003 r104178  
    372372#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    373373    {
     374#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    374375        vrc = i_openViaToolbox(pvrcGuest);
     376#else
     377        RT_NOREF(pvrcGuest);
     378        vrc = VERR_NOT_SUPPORTED;
     379#endif
    375380    }
    376381
     
    847852#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    848853    {
     854#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    849855        vrc = i_closeViaToolbox(pvrcGuest);
     856#else
     857        RT_NOREF(pvrcGuest);
     858        vrc = VERR_NOT_SUPPORTED;
     859#endif
    850860    }
    851861
     
    944954#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    945955    {
     956#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    946957        vrc = i_readInternalViaToolbox(objData, pvrcGuest);
     958#else
     959        RT_NOREF(objData, pvrcGuest);
     960        vrc = VERR_NOT_SUPPORTED;
     961#endif
    947962    }
    948963
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r104003 r104178  
    22702270///////////////////////////////////////////////////////////////////////////////
    22712271
    2272 GuestProcessToolbox::GuestProcessToolbox(void)
     2272GuestProcessWrapper::GuestProcessWrapper(void)
    22732273    : pSession(NULL),
    22742274      pProcess(NULL)
     
    22762276}
    22772277
    2278 GuestProcessToolbox::~GuestProcessToolbox(void)
     2278GuestProcessWrapper::~GuestProcessWrapper(void)
    22792279{
    22802280    uninit();
     
    22822282
    22832283/**
    2284  * Initializes and starts a process tool on the guest.
     2284 * Initializes and starts a process on the guest.
    22852285 *
    22862286 * @returns VBox status code.
    2287  * @param   pGuestSession       Guest session the process tools should be started in.
     2287 * @param   pGuestSession       Guest session the process should be started in.
    22882288 * @param   startupInfo         Guest process startup info to use for starting.
    22892289 * @param   fAsync              Whether to start asynchronously or not.
     
    22912291 *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
    22922292 */
    2293 int GuestProcessToolbox::init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
     2293int GuestProcessWrapper::init(GuestSession *pGuestSession, const GuestProcessStartupInfo &startupInfo,
    22942294                              bool fAsync, int *pvrcGuest)
    22952295{
     
    23312331
    23322332/**
    2333  * Unitializes a guest process tool by terminating it on the guest.
    2334  */
    2335 void GuestProcessToolbox::uninit(void)
     2333 * Unitializes a guest process by terminating it on the guest.
     2334 */
     2335void GuestProcessWrapper::uninit(void)
    23362336{
    23372337    /* Make sure the process is terminated and unregistered from the guest session. */
     
    23502350
    23512351/**
    2352  * Gets the current guest process stream block.
     2352 * Returns whether a guest process is still running or not.
     2353 *
     2354 * @returns \c true if running, or \c false if not.
     2355 */
     2356bool GuestProcessWrapper::isRunning(void)
     2357{
     2358    AssertReturn(!pProcess.isNull(), false);
     2359
     2360    ProcessStatus_T procStatus = ProcessStatus_Undefined;
     2361    HRESULT hrc = pProcess->COMGETTER(Status(&procStatus));
     2362    AssertComRC(hrc);
     2363
     2364    if (   procStatus == ProcessStatus_Started
     2365        || procStatus == ProcessStatus_Paused
     2366        || procStatus == ProcessStatus_Terminating)
     2367    {
     2368        return true;
     2369    }
     2370
     2371    return false;
     2372}
     2373
     2374/**
     2375 * Returns whether the guest process has been run correctly or not, based on it's internal process
     2376 * status and reported exit status.
     2377 *
     2378 * @return @c true if the guest process has been run correctly (exit status 0), or @c false if some error
     2379 *         occurred (exit status <> 0 or wrong process state).
     2380 */
     2381bool GuestProcessWrapper::isTerminatedOk(void)
     2382{
     2383    return getTerminationStatus() == VINF_SUCCESS;
     2384}
     2385
     2386
     2387/**
     2388 * Reports if the guest process has been run correctly.
     2389 *
     2390 * @retval  VINF_SUCCESS if the process has stopped and the exit code is zero.
     2391 * @retval  VERR_GSTCTL_PROCESS_EXIT_CODE if the exit code is _not_ zero.
     2392 * @retval  VERR_GSTCTL_PROCESS_WRONG_STATE if still running.
     2393 *
     2394 * @param   piExitCode      Exit code of the tool. Optional.
     2395 */
     2396int GuestProcessWrapper::getTerminationStatus(int32_t *piExitCode /* = NULL */)
     2397{
     2398    Assert(!pProcess.isNull());
     2399    AssertPtrNull(piExitCode);
     2400
     2401    int vrc;
     2402    if (!isRunning())
     2403    {
     2404        LONG iExitCode = -1;
     2405        HRESULT hrc = pProcess->COMGETTER(ExitCode(&iExitCode));
     2406        AssertComRC(hrc);
     2407
     2408        if (piExitCode)
     2409            *piExitCode = iExitCode;
     2410
     2411        vrc = iExitCode == 0 ? VINF_SUCCESS : VERR_GSTCTL_PROCESS_EXIT_CODE;
     2412    }
     2413    else
     2414    {
     2415        if (piExitCode)
     2416            *piExitCode = -1;
     2417        vrc = VERR_GSTCTL_PROCESS_WRONG_STATE;
     2418    }
     2419
     2420    LogFlowFuncLeaveRC(vrc);
     2421    return vrc;
     2422}
     2423
     2424/**
     2425 * Terminates a guest process.
     2426 *
     2427 * @returns VBox status code.
     2428 * @param   uTimeoutMS          Timeout (in ms) to wait.
     2429 * @param   pvrcGuest           Where to return the guest error when
     2430 *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
     2431 */
     2432int GuestProcessWrapper::terminate(uint32_t uTimeoutMS, int *pvrcGuest)
     2433{
     2434    LogFlowThisFuncEnter();
     2435
     2436    int vrc;
     2437    if (!pProcess.isNull())
     2438        vrc = pProcess->i_terminateProcess(uTimeoutMS, pvrcGuest);
     2439    else
     2440        vrc = VERR_NOT_FOUND;
     2441
     2442    LogFlowFuncLeaveRC(vrc);
     2443    return vrc;
     2444}
     2445
     2446///////////////////////////////////////////////////////////////////////////////
     2447
     2448#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     2449GuestProcessToolbox::GuestProcessToolbox(void)
     2450{
     2451}
     2452
     2453GuestProcessToolbox::~GuestProcessToolbox(void)
     2454{
     2455}
     2456
     2457/**
     2458 * Waits for a guest toolbox process.
     2459 *
     2460 * @returns VBox status code.
     2461 * @param   fToolWaitFlags      Guest process tool wait flags to use for waiting.
     2462 * @param   pvrcGuest           Where to return the guest error when
     2463 *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
     2464 */
     2465int GuestProcessToolbox::wait(uint32_t fToolWaitFlags, int *pvrcGuest)
     2466{
     2467    return waitEx(fToolWaitFlags, NULL /* pStrmBlkOut */, pvrcGuest);
     2468}
     2469
     2470/**
     2471 * Waits for a guest toolbox process, also returning process output.
     2472 *
     2473 * @returns VBox status code.
     2474 * @param   fToolWaitFlags      Guest process tool wait flags to use for waiting.
     2475 * @param   pStrmBlkOut         Where to store the guest toolbox output.
     2476 * @param   pvrcGuest           Where to return the guest error when
     2477 *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
     2478 */
     2479int GuestProcessToolbox::waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *pStrmBlkOut, int *pvrcGuest)
     2480{
     2481    LogFlowThisFunc(("fToolWaitFlags=0x%x, pStrmBlkOut=%p, pvrcGuest=%p\n", fToolWaitFlags, pStrmBlkOut, pvrcGuest));
     2482
     2483    int vrc;
     2484
     2485    /* Is the next block complete without waiting for new data from the guest? */
     2486    if (fToolWaitFlags & GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK)
     2487    {
     2488        AssertPtr(pStrmBlkOut);
     2489        vrc = getCurrentBlock(GUEST_PROC_OUT_H_STDOUT, *pStrmBlkOut);
     2490        if (   RT_SUCCESS(vrc)
     2491            && pStrmBlkOut->IsComplete())
     2492            return vrc;
     2493        /* else do the waiting below. */
     2494    }
     2495
     2496    /* Do the waiting. */
     2497    uint32_t fProcWaitForFlags = ProcessWaitForFlag_Terminate;
     2498    if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
     2499        fProcWaitForFlags |= ProcessWaitForFlag_StdOut;
     2500    if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdErr)
     2501        fProcWaitForFlags |= ProcessWaitForFlag_StdErr;
     2502
     2503    /** @todo Decrease timeout while running. */
     2504    uint64_t u64StartMS = RTTimeMilliTS();
     2505    uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS;
     2506
     2507    int vrcGuest = VINF_SUCCESS;
     2508    bool fDone = false;
     2509
     2510    BYTE abBuf[_64K];
     2511    uint32_t cbRead;
     2512
     2513    bool fHandleStdOut = false;
     2514    bool fHandleStdErr = false;
     2515
     2516    /**
     2517     * Updates the elapsed time and checks if a
     2518     * timeout happened, then breaking out of the loop.
     2519     */
     2520#define UPDATE_AND_CHECK_ELAPSED_TIME()          \
     2521    u64ElapsedMS = RTTimeMilliTS() - u64StartMS; \
     2522    if (   uTimeoutMS   != RT_INDEFINITE_WAIT    \
     2523        && u64ElapsedMS >= uTimeoutMS)           \
     2524    {                                            \
     2525        vrc = VERR_TIMEOUT;                      \
     2526        break;                                   \
     2527    }
     2528
     2529    /**
     2530     * Returns the remaining time (in ms).
     2531     */
     2532#define GET_REMAINING_TIME (uTimeoutMS == RT_INDEFINITE_WAIT ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS)
     2533
     2534    ProcessWaitResult_T waitRes = ProcessWaitResult_None;
     2535    do
     2536    {
     2537        uint64_t u64ElapsedMS;
     2538        UPDATE_AND_CHECK_ELAPSED_TIME();
     2539
     2540        vrc = pProcess->i_waitFor(fProcWaitForFlags, GET_REMAINING_TIME, waitRes, &vrcGuest);
     2541        if (RT_FAILURE(vrc))
     2542            break;
     2543
     2544        switch (waitRes)
     2545        {
     2546            case ProcessWaitResult_StdIn:
     2547                vrc = VERR_NOT_IMPLEMENTED;
     2548                break;
     2549
     2550            case ProcessWaitResult_StdOut:
     2551                fHandleStdOut = true;
     2552                break;
     2553
     2554            case ProcessWaitResult_StdErr:
     2555                fHandleStdErr = true;
     2556                break;
     2557
     2558            case ProcessWaitResult_WaitFlagNotSupported:
     2559                if (fProcWaitForFlags & ProcessWaitForFlag_StdOut)
     2560                    fHandleStdOut = true;
     2561                if (fProcWaitForFlags & ProcessWaitForFlag_StdErr)
     2562                    fHandleStdErr = true;
     2563                /* Since waiting for stdout / stderr is not supported by the guest,
     2564                 * wait a bit to not hog the CPU too much when polling for data. */
     2565                RTThreadSleep(1); /* Optional, don't check vrc. */
     2566                break;
     2567
     2568            case ProcessWaitResult_Error:
     2569                vrc = VERR_GSTCTL_GUEST_ERROR;
     2570                break;
     2571
     2572            case ProcessWaitResult_Terminate:
     2573                fDone = true;
     2574                break;
     2575
     2576            case ProcessWaitResult_Timeout:
     2577                vrc = VERR_TIMEOUT;
     2578                break;
     2579
     2580            case ProcessWaitResult_Start:
     2581            case ProcessWaitResult_Status:
     2582                /* Not used here, just skip. */
     2583                break;
     2584
     2585            default:
     2586                AssertMsgFailed(("Unhandled process wait result %RU32\n", waitRes));
     2587                break;
     2588        }
     2589
     2590        if (RT_FAILURE(vrc))
     2591            break;
     2592
     2593        if (fHandleStdOut)
     2594        {
     2595            UPDATE_AND_CHECK_ELAPSED_TIME();
     2596
     2597            cbRead = 0;
     2598            vrc = pProcess->i_readData(GUEST_PROC_OUT_H_STDOUT, sizeof(abBuf),
     2599                                       GET_REMAINING_TIME,
     2600                                       abBuf, sizeof(abBuf),
     2601                                       &cbRead, &vrcGuest);
     2602            if (   RT_FAILURE(vrc)
     2603                || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)
     2604                break;
     2605
     2606            if (cbRead)
     2607            {
     2608                LogFlowThisFunc(("Received %RU32 bytes from stdout\n", cbRead));
     2609                vrc = mStdOut.AddData(abBuf, cbRead);
     2610
     2611                if (   RT_SUCCESS(vrc)
     2612                    && (fToolWaitFlags & GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK))
     2613                {
     2614                    AssertPtr(pStrmBlkOut);
     2615                    vrc = getCurrentBlock(GUEST_PROC_OUT_H_STDOUT, *pStrmBlkOut);
     2616
     2617                    /* When successful, break out of the loop because we're done
     2618                     * with reading the first stream block. */
     2619                    if (RT_SUCCESS(vrc))
     2620                        fDone = true;
     2621                }
     2622            }
     2623
     2624            fHandleStdOut = false;
     2625        }
     2626
     2627        if (fHandleStdErr)
     2628        {
     2629            UPDATE_AND_CHECK_ELAPSED_TIME();
     2630
     2631            cbRead = 0;
     2632            vrc = pProcess->i_readData(GUEST_PROC_OUT_H_STDERR, sizeof(abBuf),
     2633                                       GET_REMAINING_TIME,
     2634                                       abBuf, sizeof(abBuf),
     2635                                       &cbRead, &vrcGuest);
     2636            if (   RT_FAILURE(vrc)
     2637                || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)
     2638                break;
     2639
     2640            if (cbRead)
     2641            {
     2642                LogFlowThisFunc(("Received %RU32 bytes from stderr\n", cbRead));
     2643                vrc = mStdErr.AddData(abBuf, cbRead);
     2644            }
     2645
     2646            fHandleStdErr = false;
     2647        }
     2648
     2649    } while (!fDone && RT_SUCCESS(vrc));
     2650
     2651#undef UPDATE_AND_CHECK_ELAPSED_TIME
     2652#undef GET_REMAINING_TIME
     2653
     2654    if (RT_FAILURE(vrcGuest))
     2655        vrc = VERR_GSTCTL_GUEST_ERROR;
     2656
     2657    LogFlowThisFunc(("Loop ended with vrc=%Rrc, vrcGuest=%Rrc, waitRes=%RU32\n", vrc, vrcGuest, waitRes));
     2658    if (pvrcGuest)
     2659        *pvrcGuest = vrcGuest;
     2660
     2661    LogFlowFuncLeaveRC(vrc);
     2662    return vrc;
     2663}
     2664
     2665/**
     2666 * Gets the current guest toolbox process stream block.
    23532667 *
    23542668 * @returns VBox status code.
     
    23752689
    23762690/**
    2377  * Returns the result code from an ended guest process tool.
    2378  *
    2379  * @returns Result code from guest process tool.
     2691 * Returns the result code from an ended guest toolbox process.
     2692 *
     2693 * @returns Result code from guest toolbox process.
    23802694 */
    23812695int GuestProcessToolbox::getRc(void) const
     
    23862700
    23872701    return GuestProcessToolbox::exitCodeToRc(mStartupInfo, exitCode);
    2388 }
    2389 
    2390 /**
    2391  * Returns whether a guest process tool is still running or not.
    2392  *
    2393  * @returns \c true if running, or \c false if not.
    2394  */
    2395 bool GuestProcessToolbox::isRunning(void)
    2396 {
    2397     AssertReturn(!pProcess.isNull(), false);
    2398 
    2399     ProcessStatus_T procStatus = ProcessStatus_Undefined;
    2400     HRESULT hrc = pProcess->COMGETTER(Status(&procStatus));
    2401     AssertComRC(hrc);
    2402 
    2403     if (   procStatus == ProcessStatus_Started
    2404         || procStatus == ProcessStatus_Paused
    2405         || procStatus == ProcessStatus_Terminating)
    2406     {
    2407         return true;
    2408     }
    2409 
    2410     return false;
    2411 }
    2412 
    2413 /**
    2414  * Returns whether the tool has been run correctly or not, based on it's internal process
    2415  * status and reported exit status.
    2416  *
    2417  * @return @c true if the tool has been run correctly (exit status 0), or @c false if some error
    2418  *         occurred (exit status <> 0 or wrong process state).
    2419  */
    2420 bool GuestProcessToolbox::isTerminatedOk(void)
    2421 {
    2422     return getTerminationStatus() == VINF_SUCCESS;
    24232702}
    24242703
     
    25252804
    25262805/**
    2527  * Reports if the tool has been run correctly.
    2528  *
    2529  * @retval  VINF_SUCCESS if the process has stopped and the exit code is zero.
    2530  * @retval  VERR_GSTCTL_PROCESS_EXIT_CODE if the exit code is _not_ zero.
    2531  * @retval  VERR_GSTCTL_PROCESS_WRONG_STATE if still running.
    2532  *
    2533  * @param   piExitCode      Exit code of the tool. Optional.
    2534  */
    2535 int GuestProcessToolbox::getTerminationStatus(int32_t *piExitCode /* = NULL */)
    2536 {
    2537     Assert(!pProcess.isNull());
    2538     AssertPtrNull(piExitCode);
    2539 
    2540     int vrc;
    2541     if (!isRunning())
    2542     {
    2543         LONG iExitCode = -1;
    2544         HRESULT hrc = pProcess->COMGETTER(ExitCode(&iExitCode));
    2545         AssertComRC(hrc);
    2546 
    2547         if (piExitCode)
    2548             *piExitCode = iExitCode;
    2549 
    2550         vrc = iExitCode == 0 ? VINF_SUCCESS : VERR_GSTCTL_PROCESS_EXIT_CODE;
    2551     }
    2552     else
    2553     {
    2554         if (piExitCode)
    2555             *piExitCode = -1;
    2556         vrc = VERR_GSTCTL_PROCESS_WRONG_STATE;
    2557     }
    2558 
    2559     LogFlowFuncLeaveRC(vrc);
    2560     return vrc;
    2561 }
    2562 
    2563 /**
    2564  * Waits for a guest process tool.
    2565  *
    2566  * @returns VBox status code.
    2567  * @param   fToolWaitFlags      Guest process tool wait flags to use for waiting.
    2568  * @param   pvrcGuest           Where to return the guest error when
    2569  *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
    2570  */
    2571 int GuestProcessToolbox::wait(uint32_t fToolWaitFlags, int *pvrcGuest)
    2572 {
    2573     return waitEx(fToolWaitFlags, NULL /* pStrmBlkOut */, pvrcGuest);
    2574 }
    2575 
    2576 /**
    2577  * Waits for a guest process tool, also returning process output.
    2578  *
    2579  * @returns VBox status code.
    2580  * @param   fToolWaitFlags      Guest process tool wait flags to use for waiting.
    2581  * @param   pStrmBlkOut         Where to store the guest process output.
    2582  * @param   pvrcGuest           Where to return the guest error when
    2583  *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
    2584  */
    2585 int GuestProcessToolbox::waitEx(uint32_t fToolWaitFlags, GuestToolboxStreamBlock *pStrmBlkOut, int *pvrcGuest)
    2586 {
    2587     LogFlowThisFunc(("fToolWaitFlags=0x%x, pStreamBlock=%p, pvrcGuest=%p\n", fToolWaitFlags, pStrmBlkOut, pvrcGuest));
    2588 
    2589     int vrc;
    2590 
    2591     /* Is the next block complete without waiting for new data from the guest? */
    2592     if (fToolWaitFlags & GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK)
    2593     {
    2594         AssertPtr(pStrmBlkOut);
    2595         vrc = getCurrentBlock(GUEST_PROC_OUT_H_STDOUT, *pStrmBlkOut);
    2596         if (   RT_SUCCESS(vrc)
    2597             && pStrmBlkOut->IsComplete())
    2598             return vrc;
    2599         /* else do the waiting below. */
    2600     }
    2601 
    2602     /* Do the waiting. */
    2603     uint32_t fProcWaitForFlags = ProcessWaitForFlag_Terminate;
    2604     if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
    2605         fProcWaitForFlags |= ProcessWaitForFlag_StdOut;
    2606     if (mStartupInfo.mFlags & ProcessCreateFlag_WaitForStdErr)
    2607         fProcWaitForFlags |= ProcessWaitForFlag_StdErr;
    2608 
    2609     /** @todo Decrease timeout while running. */
    2610     uint64_t u64StartMS = RTTimeMilliTS();
    2611     uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS;
    2612 
    2613     int vrcGuest = VINF_SUCCESS;
    2614     bool fDone = false;
    2615 
    2616     BYTE abBuf[_64K];
    2617     uint32_t cbRead;
    2618 
    2619     bool fHandleStdOut = false;
    2620     bool fHandleStdErr = false;
    2621 
    2622     /**
    2623      * Updates the elapsed time and checks if a
    2624      * timeout happened, then breaking out of the loop.
    2625      */
    2626 #define UPDATE_AND_CHECK_ELAPSED_TIME()          \
    2627     u64ElapsedMS = RTTimeMilliTS() - u64StartMS; \
    2628     if (   uTimeoutMS   != RT_INDEFINITE_WAIT    \
    2629         && u64ElapsedMS >= uTimeoutMS)           \
    2630     {                                            \
    2631         vrc = VERR_TIMEOUT;                      \
    2632         break;                                   \
    2633     }
    2634 
    2635     /**
    2636      * Returns the remaining time (in ms).
    2637      */
    2638 #define GET_REMAINING_TIME (uTimeoutMS == RT_INDEFINITE_WAIT ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS)
    2639 
    2640     ProcessWaitResult_T waitRes = ProcessWaitResult_None;
    2641     do
    2642     {
    2643         uint64_t u64ElapsedMS;
    2644         UPDATE_AND_CHECK_ELAPSED_TIME();
    2645 
    2646         vrc = pProcess->i_waitFor(fProcWaitForFlags, GET_REMAINING_TIME, waitRes, &vrcGuest);
    2647         if (RT_FAILURE(vrc))
    2648             break;
    2649 
    2650         switch (waitRes)
    2651         {
    2652             case ProcessWaitResult_StdIn:
    2653                 vrc = VERR_NOT_IMPLEMENTED;
    2654                 break;
    2655 
    2656             case ProcessWaitResult_StdOut:
    2657                 fHandleStdOut = true;
    2658                 break;
    2659 
    2660             case ProcessWaitResult_StdErr:
    2661                 fHandleStdErr = true;
    2662                 break;
    2663 
    2664             case ProcessWaitResult_WaitFlagNotSupported:
    2665                 if (fProcWaitForFlags & ProcessWaitForFlag_StdOut)
    2666                     fHandleStdOut = true;
    2667                 if (fProcWaitForFlags & ProcessWaitForFlag_StdErr)
    2668                     fHandleStdErr = true;
    2669                 /* Since waiting for stdout / stderr is not supported by the guest,
    2670                  * wait a bit to not hog the CPU too much when polling for data. */
    2671                 RTThreadSleep(1); /* Optional, don't check vrc. */
    2672                 break;
    2673 
    2674             case ProcessWaitResult_Error:
    2675                 vrc = VERR_GSTCTL_GUEST_ERROR;
    2676                 break;
    2677 
    2678             case ProcessWaitResult_Terminate:
    2679                 fDone = true;
    2680                 break;
    2681 
    2682             case ProcessWaitResult_Timeout:
    2683                 vrc = VERR_TIMEOUT;
    2684                 break;
    2685 
    2686             case ProcessWaitResult_Start:
    2687             case ProcessWaitResult_Status:
    2688                 /* Not used here, just skip. */
    2689                 break;
    2690 
    2691             default:
    2692                 AssertMsgFailed(("Unhandled process wait result %RU32\n", waitRes));
    2693                 break;
    2694         }
    2695 
    2696         if (RT_FAILURE(vrc))
    2697             break;
    2698 
    2699         if (fHandleStdOut)
    2700         {
    2701             UPDATE_AND_CHECK_ELAPSED_TIME();
    2702 
    2703             cbRead = 0;
    2704             vrc = pProcess->i_readData(GUEST_PROC_OUT_H_STDOUT, sizeof(abBuf),
    2705                                        GET_REMAINING_TIME,
    2706                                        abBuf, sizeof(abBuf),
    2707                                        &cbRead, &vrcGuest);
    2708             if (   RT_FAILURE(vrc)
    2709                 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)
    2710                 break;
    2711 
    2712             if (cbRead)
    2713             {
    2714                 LogFlowThisFunc(("Received %RU32 bytes from stdout\n", cbRead));
    2715                 vrc = mStdOut.AddData(abBuf, cbRead);
    2716 
    2717                 if (   RT_SUCCESS(vrc)
    2718                     && (fToolWaitFlags & GUESTPROCESSTOOL_WAIT_FLAG_STDOUT_BLOCK))
    2719                 {
    2720                     AssertPtr(pStrmBlkOut);
    2721                     vrc = getCurrentBlock(GUEST_PROC_OUT_H_STDOUT, *pStrmBlkOut);
    2722 
    2723                     /* When successful, break out of the loop because we're done
    2724                      * with reading the first stream block. */
    2725                     if (RT_SUCCESS(vrc))
    2726                         fDone = true;
    2727                 }
    2728             }
    2729 
    2730             fHandleStdOut = false;
    2731         }
    2732 
    2733         if (fHandleStdErr)
    2734         {
    2735             UPDATE_AND_CHECK_ELAPSED_TIME();
    2736 
    2737             cbRead = 0;
    2738             vrc = pProcess->i_readData(GUEST_PROC_OUT_H_STDERR, sizeof(abBuf),
    2739                                        GET_REMAINING_TIME,
    2740                                        abBuf, sizeof(abBuf),
    2741                                        &cbRead, &vrcGuest);
    2742             if (   RT_FAILURE(vrc)
    2743                 || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)
    2744                 break;
    2745 
    2746             if (cbRead)
    2747             {
    2748                 LogFlowThisFunc(("Received %RU32 bytes from stderr\n", cbRead));
    2749                 vrc = mStdErr.AddData(abBuf, cbRead);
    2750             }
    2751 
    2752             fHandleStdErr = false;
    2753         }
    2754 
    2755     } while (!fDone && RT_SUCCESS(vrc));
    2756 
    2757 #undef UPDATE_AND_CHECK_ELAPSED_TIME
    2758 #undef GET_REMAINING_TIME
    2759 
    2760     if (RT_FAILURE(vrcGuest))
    2761         vrc = VERR_GSTCTL_GUEST_ERROR;
    2762 
    2763     LogFlowThisFunc(("Loop ended with vrc=%Rrc, vrcGuest=%Rrc, waitRes=%RU32\n", vrc, vrcGuest, waitRes));
    2764     if (pvrcGuest)
    2765         *pvrcGuest = vrcGuest;
    2766 
    2767     LogFlowFuncLeaveRC(vrc);
    2768     return vrc;
    2769 }
    2770 
    2771 /**
    2772  * Terminates a guest process tool.
    2773  *
    2774  * @returns VBox status code.
    2775  * @param   uTimeoutMS          Timeout (in ms) to wait.
    2776  * @param   pvrcGuest           Where to return the guest error when
    2777  *                              VERR_GSTCTL_GUEST_ERROR was returned. Optional.
    2778  */
    2779 int GuestProcessToolbox::terminate(uint32_t uTimeoutMS, int *pvrcGuest)
    2780 {
    2781     LogFlowThisFuncEnter();
    2782 
    2783     int vrc;
    2784     if (!pProcess.isNull())
    2785         vrc = pProcess->i_terminateProcess(uTimeoutMS, pvrcGuest);
    2786     else
    2787         vrc = VERR_NOT_FOUND;
    2788 
    2789     LogFlowFuncLeaveRC(vrc);
    2790     return vrc;
    2791 }
    2792 
    2793 /**
    27942806 * Converts a toolbox tool's exit code to an IPRT error code.
    27952807 *
     
    29612973    return strErr;
    29622974}
    2963 
     2975#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r104003 r104178  
    10911091#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    10921092    {
     1093#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    10931094        vrc = i_directoryCreateViaToolbox(strPath, uMode, uFlags, pvrcGuest);
     1095#else
     1096        RT_NOREF(uMode, uFlags, pvrcGuest);
     1097        vrc = VERR_NOT_SUPPORTED;
     1098#endif
    10941099    }
    10951100
     
    12551260}
    12561261
     1262#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    12571263/**
    12581264 * Creates a temporary directory / file on the guest (legacy version).
     
    13421348    return vrc;
    13431349}
     1350#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    13441351
    13451352/**
     
    14301437#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    14311438    {
     1439#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    14321440        vrc = i_fsCreateTempViaToolbox(strTemplate, strPath, fDirectory, strName, fMode, fSecure, pvrcGuest);
     1441#else
     1442        RT_NOREF(strTemplate, strPath, fDirectory, strName, fMode, fSecure, pvrcGuest);
     1443        vrc = VERR_NOT_SUPPORTED;
     1444#endif
    14331445    }
    14341446
     
    17691781}
    17701782
     1783#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    17711784/**
    17721785 * Removes a file from the guest (legacy version).
     
    18231836    return vrc;
    18241837}
     1838#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    18251839
    18261840/**
     
    18711885#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    18721886    {
     1887#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    18731888        vrc = i_fileRemoveViaToolbox(strPath, pvrcGuest);
     1889#else
     1890        RT_NOREF(strPath, pvrcGuest);
     1891        vrc = VERR_NOT_SUPPORTED;
     1892#endif
    18741893    }
    18751894
     
    20482067}
    20492068
     2069#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    20502070/**
    20512071 * Queries information of a file system object (file, directory, ...). Legacy version.
     
    21042124    return vrc;
    21052125}
     2126#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    21062127
    21072128/**
     
    22502271#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
    22512272    {
     2273#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
    22522274        vrc = i_fsObjQueryInfoViaToolbox(strPath, fFollowSymlinks, objData, pvrcGuest);
     2275#else
     2276        RT_NOREF(strPath, fFollowSymlinks, objData, pvrcGuest);
     2277        vrc = VERR_NOT_SUPPORTED;
     2278#endif
    22532279    }
    22542280
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r104161 r104178  
    26272627    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    26282628
     2629#ifndef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
     2630    RT_NOREF(procInfo, fSilent);
     2631    return VERR_NOT_SUPPORTED;
     2632#else
    26292633    LogRel(("Running %s ...\n", procInfo.mName.c_str()));
    26302634
     
    26712675
    26722676    return vrc;
     2677#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
    26732678}
    26742679
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette