VirtualBox

Changeset 38395 in vbox for trunk/src


Ignore:
Timestamp:
Aug 10, 2011 11:48:29 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
73430
Message:

GuestCtrl: Update.

Location:
trunk/src/VBox
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r38180 r38395  
    13591359    Assert(uStatus > INPUT_STS_UNDEFINED);
    13601360
    1361     VBoxServiceVerbose(3, "ControlExec: [PID %u]: Input processed, uStatus=%u, uFlags=0x%x, cbWritten=%u\n",
    1362                        uPID, uStatus, uFlags, cbWritten);
     1361    VBoxServiceVerbose(3, "ControlExec: [PID %u]: Input processed, CID=%u, uStatus=%u, uFlags=0x%x, cbWritten=%u\n",
     1362                       uPID, uContextID, uStatus, uFlags, cbWritten);
    13631363
    13641364    /* Note: Since the context ID is unique the request *has* to be completed here,
     
    14011401                                                       pBuf, _64K /* cbSize */, &cbRead);
    14021402            if (RT_SUCCESS(rc))
    1403                 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Got output, cbRead=%u, uHandle=%u, uFlags=%u\n",
    1404                                    uPID, cbRead, uHandleID, uFlags);
     1403                VBoxServiceVerbose(3, "ControlExec: [PID %u]: Got output, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n",
     1404                                   uPID, uContextID, cbRead, uHandleID, uFlags);
    14051405            else
    1406                 VBoxServiceError("ControlExec: [PID %u]: Failed to retrieve output, uHandle=%u, rc=%Rrc\n",
    1407                                  uPID, uHandleID, rc);
     1406                VBoxServiceError("ControlExec: [PID %u]: Failed to retrieve output, CID=%u, uHandle=%u, rc=%Rrc\n",
     1407                                 uPID, uContextID, uHandleID, rc);
    14081408
    14091409            /* Note: Since the context ID is unique the request *has* to be completed here,
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r38290 r38395  
    7979
    8080/**
    81  * An entry for a source element, including an optional filter.
     81 * An entry for a source element, including an optional DOS-like wildcard (*,?).
    8282 */
    8383typedef struct SOURCEFILEENTRY
     
    9393        {
    9494            /* No file and no directory -- maybe a filter? */
    95             if (NULL != strpbrk(RTPathFilename(pszSource), "*?"))
     95            char *pszFilename = RTPathFilename(pszSource);
     96            if (   pszFilename
     97                && strpbrk(pszFilename, "*?"))
    9698            {
    9799                /* Yep, get the actual filter part. */
     
    938940    {
    939941        BOOL fDirExists = FALSE;
    940         HRESULT hr = pContext->pGuest->FileExists(Bstr(pszDir).raw(),
    941                                                   Bstr(pContext->pszUsername).raw(),
    942                                                   Bstr(pContext->pszPassword).raw(), &fDirExists);
     942        HRESULT hr = pContext->pGuest->DirectoryExists(Bstr(pszDir).raw(),
     943                                                       Bstr(pContext->pszUsername).raw(),
     944                                                       Bstr(pContext->pszPassword).raw(), &fDirExists);
    943945        if (FAILED(hr))
    944946            rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
     
    12711273                case GuestDirEntryType_File:
    12721274                {
    1273                     const char *pszName = Utf8Str(strName).c_str();
     1275                    Utf8Str strFile(strName);
    12741276                    if (   !pszFilter
    1275                         || RTStrSimplePatternMatch(pszFilter, pszName))
     1277                        || RTStrSimplePatternMatch(pszFilter, strFile.c_str()))
    12761278                    {
    12771279                        if (!fDirCreated)
     
    12911293                        if (RT_SUCCESS(rc))
    12921294                        {
    1293                             Utf8Str strDir(strName);
    12941295                            char *pszFileSource;
    12951296                            if (RTStrAPrintf(&pszFileSource, "%s/%s",
    1296                                              szCurDir, strDir.c_str()))
     1297                                             szCurDir, strFile.c_str()))
    12971298                            {
    12981299                                char *pszFileDest;
     
    13071308                                RTStrFree(pszFileSource);
    13081309                            }
     1310                            else
     1311                                rc = VERR_NO_MEMORY;
    13091312                        }
    13101313                    }
     
    13151318                    break;
    13161319            }
    1317         }
    1318 
    1319         hr = pContext->pGuest->DirectoryClose(uDirHandle);
    1320         if (FAILED(rc))
    1321             rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
     1320
     1321            if (RT_FAILURE(rc))
     1322                break;
     1323        }
     1324
     1325        if (FAILED(hr))
     1326        {
     1327            if (hr != E_ABORT)
     1328                rc = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
     1329        }
     1330
     1331        HRESULT hr2 = pContext->pGuest->DirectoryClose(uDirHandle);
     1332        if (FAILED(hr2))
     1333        {
     1334            int rc2 = ctrlPrintError(pContext->pGuest, COM_IIDOF(IGuest));
     1335            if (RT_SUCCESS(rc))
     1336                rc = rc2;
     1337        }
     1338        else if (SUCCEEDED(hr))
     1339            hr = hr2;
    13221340    }
    13231341
     
    15491567                RTPrintf("Source: %s\n", pszSource);
    15501568
    1551             /* @todo Files with filter?? */
     1569            /** @todo Files with filter?? */
    15521570            bool fExists;
    15531571            vrc = ctrlCopyFileExistsOnSource(pContext, pszSource, &fExists);
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r38186 r38395  
    85668566  <interface
    85678567    name="IGuest" extends="$unknown"
    8568     uuid="ed109b6e-0578-4b17-8ace-52646789f1a0"
     8568    uuid="35f75ed7-df96-4988-b246-2c103555c95d"
    85698569    wsmap="managed"
    85708570    >
     
    90099009        <desc>
    90109010          <link to="DirectoryCreateFlag"/> flags.
     9011        </desc>
     9012      </param>
     9013    </method>
     9014
     9015    <method name="directoryExists">
     9016      <desc>
     9017        Checks if the specified directory exists and is a directory.
     9018
     9019        <result name="VBOX_E_IPRT_ERROR">
     9020          Error while looking up information.
     9021        </result>
     9022
     9023      </desc>
     9024      <param name="directory" type="wstring" dir="in">
     9025        <desc>
     9026          Full path of directory to check.
     9027        </desc>
     9028      </param>
     9029      <param name="userName" type="wstring" dir="in">
     9030        <desc>
     9031          User name under which the lookup will be performed; the
     9032          user has to exist and have the appropriate rights to access / read the
     9033          desired directory.
     9034        </desc>
     9035      </param>
     9036      <param name="password" type="wstring" dir="in">
     9037        <desc>
     9038          Password of the user account specified.
     9039        </desc>
     9040      </param>
     9041      <param name="exists" type="boolean" dir="return">
     9042        <desc>
     9043          True if it's a directory, false if it isn't (or doesn't exist).
    90119044        </desc>
    90129045      </param>
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r38290 r38395  
    3939typedef struct VBOXGUESTCTRL_STREAMPAIR
    4040{
    41     char *pszValue;
     41    VBOXGUESTCTRL_STREAMPAIR(const char *pszValue)
     42        : mValue(pszValue) {}
     43
     44    Utf8Str mValue;
    4245} VBOXGUESTCTRL_STREAMPAIR, *PVBOXGUESTCTRL_STREAM_PAIR;
    4346
     
    5861    GuestProcessStreamBlock();
    5962
     63    //GuestProcessStreamBlock(GuestProcessStreamBlock &);
     64
    6065    virtual ~GuestProcessStreamBlock();
    6166
    6267public:
    63 
    64     int AddKey(const char *pszKey);
    6568
    6669    void Clear();
     
    8588};
    8689
    87 /** Vector containing multiple stream pair objects. */
    88 typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects;
     90/** Vector containing multiple allocated stream pair objects. */
     91typedef std::vector< GuestProcessStreamBlock* > GuestCtrlStreamObjects;
     92typedef std::vector< GuestProcessStreamBlock* >::iterator GuestCtrlStreamObjectsIter;
     93typedef std::vector< GuestProcessStreamBlock* >::const_iterator GuestCtrlStreamObjectsIterConst;
    8994
    9095/**
     
    110115
    111116    int ParseBlock(GuestProcessStreamBlock &streamBlock);
     117
     118public:
     119
     120    static void FreeBlock(GuestProcessStreamBlock *pStreamBlock);
    112121
    113122protected:
  • trunk/src/VBox/Main/include/GuestImpl.h

    r38290 r38395  
    2727#include "HGCM.h"
    2828#ifdef VBOX_WITH_GUEST_CONTROL
     29# include <iprt/fs.h>
    2930# include <VBox/HostServices/GuestControlSvc.h>
    3031using namespace guestControl;
     
    103104    STDMETHOD(DirectoryClose)(ULONG aHandle);
    104105    STDMETHOD(DirectoryCreate)(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, ULONG aMode, ULONG aFlags);
     106    STDMETHOD(DirectoryExists)(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists);
    105107    STDMETHOD(DirectoryOpen)(IN_BSTR aDirectory, IN_BSTR aFilter,
    106108                             ULONG aFlags, IN_BSTR aUsername, IN_BSTR aPassword, ULONG *aHandle);
     
    131133
    132134# ifdef VBOX_WITH_GUEST_CONTROL
     135    // Internal guest directory functions
     136    int directoryCreateHandle(ULONG *puHandle, ULONG uPID, IN_BSTR aDirectory, IN_BSTR aFilter, ULONG uFlags);
    133137    HRESULT directoryCreateInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword,
    134138                                    ULONG aMode, ULONG aFlags, int *pRC);
     139    void directoryDestroyHandle(uint32_t uHandle);
     140    HRESULT directoryExistsInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists);
     141    uint32_t directoryGetPID(uint32_t uHandle);
     142    int directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock);
     143    bool directoryHandleExists(uint32_t uHandle);
    135144    HRESULT directoryOpenInternal(IN_BSTR aDirectory, IN_BSTR aFilter,
    136145                                  ULONG aFlags,
    137146                                  IN_BSTR aUsername, IN_BSTR aPassword,
    138147                                  ULONG *aHandle, int *pRC);
     148    HRESULT directoryQueryInfoInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs, int *pRC);
     149    // Internal guest execution functions
    139150    HRESULT executeAndWaitForTool(IN_BSTR aTool, IN_BSTR aDescription,
    140151                                  ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
     
    146157                                   ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress, int *pRC);
    147158    HRESULT executeProcessResult(const char *pszCommand, const char *pszUser, ULONG ulTimeout, PCALLBACKDATAEXECSTATUS pExecStatus, ULONG *puPID);
    148     HRESULT executeStreamCollectBlock(ULONG aPID,
    149                                       GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock);
    150     HRESULT executeStreamCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects);
     159    HRESULT executeStreamQueryFsObjInfo(IN_BSTR aObjName,GuestProcessStreamBlock *pStreamBlock, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttribs);
     160    int     executeStreamDrain(ULONG aPID, GuestProcessStream &stream);
     161    void    executeStreamFree(GuestCtrlStreamObjects &streamObjects);
     162    void    executeStreamFreeBlock(GuestProcessStreamBlock *pBlock);
     163    int     executeStreamGetNextBlock(ULONG aPID, GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock);
     164    HRESULT executeStreamParse(ULONG aPID, GuestCtrlStreamObjects &streamObjects);
    151165    HRESULT executeWaitForStatusChange(ULONG uPID, ULONG uTimeoutMS, ExecuteProcessStatus_T *pRetStatus, ULONG *puRetExitCode);
    152     HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists, int *pRC);
    153     HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize, int *pRC);
     166    // Internal guest file functions
     167    HRESULT fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists);
     168    HRESULT fileQueryInfoInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs, int *pRC);
     169    HRESULT fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize);
    154170
    155171    // Guest control dispatcher.
     
    188204    int callbackGetUserData(uint32_t uContextID, eVBoxGuestCtrlCallbackType *pEnmType, void **ppvData, size_t *pcbData);
    189205    void* callbackGetUserDataMutableRaw(uint32_t uContextID, size_t *pcbData);
     206    int callbackInit(PVBOXGUESTCTRL_CALLBACK pCallback, eVBoxGuestCtrlCallbackType enmType, ComPtr<Progress> pProgress);
    190207    bool callbackIsCanceled(uint32_t uContextID);
    191208    bool callbackIsComplete(uint32_t uContextID);
     
    219236    typedef struct VBOXGUESTCTRL_DIRECTORY
    220237    {
    221         char                       *mpszDirectory;
    222         char                       *mpszFilter;
     238        Bstr                        mDirectory;
     239        Bstr                        mFilter;
    223240        ULONG                       mFlags;
    224241        /** Associated PID of started vbox_ls tool. */
    225         uint32_t                    mPID;
     242        ULONG                       mPID;
    226243        GuestProcessStream          mStream;
    227244#if 0
     
    237254    typedef std::map< uint32_t, VBOXGUESTCTRL_DIRECTORY >::const_iterator GuestDirectoryMapIterConst;
    238255
    239     int directoryCreateHandle(ULONG *puHandle, ULONG uPID, const char *pszDirectory, const char *pszFilter, ULONG uFlags);
    240     void directoryDestroyHandle(uint32_t uHandle);
    241     uint32_t directoryGetPID(uint32_t uHandle);
    242     int directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock);
    243     bool directoryHandleExists(uint32_t uHandle);
    244 
    245256    // Utility functions.
    246257    int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv);
  • trunk/src/VBox/Main/src-client/GuestCtrlIO.cpp

    r38269 r38395  
    3535}
    3636
     37/*
     38GuestProcessStreamBlock::GuestProcessStreamBlock(const GuestProcessStreamBlock &otherBlock)
     39{
     40    for (GuestCtrlStreamPairsIter it = otherBlock.m_mapPairs.begin();
     41         it != otherBlock.end(); it++)
     42    {
     43        m_mapPairs[it->first] = new
     44        if (it->second.pszValue)
     45        {
     46            RTMemFree(it->second.pszValue);
     47            it->second.pszValue = NULL;
     48        }
     49    }
     50}*/
     51
    3752GuestProcessStreamBlock::~GuestProcessStreamBlock()
    3853{
     
    4156
    4257/**
    43  * Adds a key (if not existing yet).
     58 * Destroys the currently stored stream pairs.
    4459 *
    4560 * @return  IPRT status code.
    46  * @param   pszKey              Key name to add.
    47  */
    48 int GuestProcessStreamBlock::AddKey(const char *pszKey)
    49 {
    50     AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
    51     /** @todo Add check for already existing keys! (VERR_ALREADY_EXISTS). */
    52     m_mapPairs[Utf8Str(pszKey)].pszValue = NULL;
    53 
    54     return VINF_SUCCESS;
    55 }
    56 
    57 /**
    58  * Destroys the currently stored stream pairs.
    59  *
    60  * @return  IPRT status code.
    6161 */
    6262void GuestProcessStreamBlock::Clear()
    6363{
    64     for (GuestCtrlStreamPairsIter it = m_mapPairs.begin(); it != m_mapPairs.end(); it++)
    65     {
    66         if (it->second.pszValue)
    67             RTMemFree(it->second.pszValue);
    68     }
    69 
    7064    m_mapPairs.clear();
    7165}
     
    115109}
    116110
    117 
    118111/**
    119112 * Returns a string value of a specified key.
     
    130123        GuestCtrlStreamPairsIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));
    131124        if (itPairs != m_mapPairs.end())
    132             return itPairs->second.pszValue;
     125            return itPairs->second.mValue.c_str();
    133126    }
    134127    catch (const std::exception &ex)
     
    185178
    186179    int rc = VINF_SUCCESS;
    187     if (pszValue)
    188     {
    189         char *pszVal = RTStrDup(pszValue);
    190         if (pszVal)
    191             m_mapPairs[pszKey].pszValue = pszVal;
    192         else
    193             rc = VERR_NO_MEMORY;
    194     }
    195     else
    196     {
    197         GuestCtrlStreamPairsIter it = m_mapPairs.find(pszKey);
    198         if (it != m_mapPairs.end())
    199         {
    200             if (it->second.pszValue)
    201             {
    202                 RTMemFree(it->second.pszValue);
    203                 it->second.pszValue = NULL;
    204             }
    205             m_mapPairs.erase(it);
    206         }
     180    try
     181    {
     182        Utf8Str Utf8Key(pszKey);
     183
     184        /* Take a shortcut and prevent crashes on some funny versions
     185         * of STL if map is empty initially. */
     186        if (!m_mapPairs.empty())
     187        {
     188            GuestCtrlStreamPairsIter it = m_mapPairs.find(Utf8Key);
     189            if (it != m_mapPairs.end())
     190                 m_mapPairs.erase(it);
     191        }
     192
     193        if (pszValue)
     194        {
     195            m_mapPairs.insert(
     196                std::pair<Utf8Str, VBOXGUESTCTRL_STREAMPAIR>(Utf8Key, VBOXGUESTCTRL_STREAMPAIR(pszValue)));
     197        }
     198    }
     199    catch (const std::exception &ex)
     200    {
     201        NOREF(ex);
    207202    }
    208203    return rc;
     
    324319
    325320/**
    326  * Try to parse the next upcoming pair block within the internal
    327  * buffer. Old pairs from a previously parsed block will be removed first!
    328  *
    329  * @return  IPRT status code.
     321 * Tries to parse the next upcoming pair block within the internal
     322 * buffer.
     323 *
     324 * Returns VERR_NO_DATA is no data is in internal buffer or buffer has been
     325 * completely parsed already.
     326 *
     327 * Returns VERR_MORE_DATA if current block was parsed (with zero or more pairs
     328 * stored in stream block) but still contains incomplete (unterminated)
     329 * data.
     330 *
     331 * Returns VINF_SUCCESS if current block was parsed until the next upcoming
     332 * block (with zero or more pairs stored in stream block).
     333 *
     334 * @return IPRT status code.
     335 * @param streamBlock               Reference to guest stream block to fill.
     336 *
    330337 */
    331338int GuestProcessStream::ParseBlock(GuestProcessStreamBlock &streamBlock)
    332339{
    333     AssertPtrReturn(m_pbBuffer, VINF_SUCCESS);
    334     AssertReturn(m_cbSize, VINF_SUCCESS);
     340    if (   !m_pbBuffer
     341        || !m_cbSize)
     342    {
     343        return VERR_NO_DATA;
     344    }
     345
    335346    AssertReturn(m_cbOffset <= m_cbSize, VERR_INVALID_PARAMETER);
     347    if (m_cbOffset == m_cbSize)
     348        return VERR_NO_DATA;
    336349
    337350    int rc = VINF_SUCCESS;
    338351
    339     size_t uCur = m_cbOffset;
    340     for (;uCur < m_cbSize;)
    341     {
    342         const char *pszStart = (char*)&m_pbBuffer[uCur];
    343         const char *pszEnd = pszStart;
    344 
    345         /* Search end of current pair (key=value\0). */
    346         while (uCur++ < m_cbSize)
    347         {
    348             if (*pszEnd == '\0')
     352    char *pszOff   = (char*)&m_pbBuffer[m_cbOffset];
     353    char *pszStart = pszOff;
     354    while (*pszStart)
     355    {
     356        size_t pairLen = strlen(pszStart);
     357        if ((pszStart - pszOff) + pairLen + 1 >= m_cbSize)
     358        {
     359            rc = VERR_MORE_DATA;
     360            break;
     361        }
     362        else
     363        {
     364            char *pszSep = strchr(pszStart, '=');
     365            char *pszVal = NULL;
     366            if (pszSep)
     367                pszVal = pszSep + 1;
     368            if (!pszSep || !pszVal)
     369            {
     370                rc = VERR_MORE_DATA;
    349371                break;
    350             pszEnd++;
    351         }
    352 
    353         size_t uPairLen = pszEnd - pszStart;
    354         if (uPairLen)
    355         {
    356             const char *pszSep = pszStart;
    357             while (   *pszSep != '='
    358                    &&  pszSep != pszEnd)
    359             {
    360                 pszSep++;
    361372            }
    362373
    363             /* No separator found (or incomplete key=value pair)? */
    364             if (   pszSep == pszStart
    365                 || pszSep == pszEnd)
    366             {
    367                 m_cbOffset =  uCur - uPairLen - 1;
    368                 rc = VERR_MORE_DATA;
    369             }
    370 
     374            /* Terminate the separator so that we can
     375             * use pszStart as our key from now on. */
     376            *pszSep = '\0';
     377
     378            rc = streamBlock.SetValue(pszStart, pszVal);
    371379            if (RT_FAILURE(rc))
    372                 break;
    373 
    374             size_t uKeyLen = pszSep - pszStart;
    375             size_t uValLen = pszEnd - (pszSep + 1);
    376 
    377             /* Get key (if present). */
    378             if (uKeyLen)
    379             {
    380                 Assert(pszSep > pszStart);
    381                 char *pszKey = (char*)RTMemAllocZ(uKeyLen + 1);
    382                 if (!pszKey)
    383                 {
    384                     rc = VERR_NO_MEMORY;
    385                     break;
    386                 }
    387                 memcpy(pszKey, pszStart, uKeyLen);
    388 
    389                 streamBlock.AddKey(pszKey);
    390 
    391                 /* Get value (if present). */
    392                 if (uValLen)
    393                 {
    394                     Assert(pszEnd > pszSep);
    395                     char *pszVal = (char*)RTMemAllocZ(uValLen + 1);
    396                     if (!pszVal)
    397                     {
    398                         rc = VERR_NO_MEMORY;
    399                         break;
    400                     }
    401                     memcpy(pszVal, pszSep + 1, uValLen);
    402 
    403                     streamBlock.SetValue(pszKey, pszVal);
    404                     RTMemFree(pszVal);
    405                 }
    406 
    407                 RTMemFree(pszKey);
    408 
    409                 m_cbOffset += uCur - m_cbOffset;
    410             }
    411         }
    412         else /* No pair detected, check for a new block. */
    413         {
    414             do
    415             {
    416                 if (*pszEnd == '\0')
    417                 {
    418                     m_cbOffset = uCur;
    419                     rc = VERR_MORE_DATA;
    420                     break;
    421                 }
    422                 pszEnd++;
    423             } while (++uCur < m_cbSize);
    424         }
    425 
    426         if (RT_FAILURE(rc))
    427             break;
    428     }
    429 
    430     RT_CLAMP(m_cbOffset, 0, m_cbSize);
     380                return rc;
     381        }
     382
     383        /* Next pair. */
     384        pszStart += pairLen + 1;
     385    }
     386
     387    /* If we did not do any movement but we have stuff left
     388     * in our buffer just skip the current termination so that
     389     * we can try next time. */
     390    uint32_t uDistance = (pszStart - pszOff);
     391    if (   !uDistance
     392        && *pszStart == '\0'
     393        && m_cbOffset < m_cbSize)
     394    {
     395        uDistance++;
     396    }
     397    m_cbOffset += uDistance;
    431398
    432399    return rc;
    433400}
    434401
     402void GuestProcessStream::FreeBlock(GuestProcessStreamBlock *pStreamBlock)
     403{
     404    if (pStreamBlock)
     405    {
     406        pStreamBlock->Clear();
     407        delete pStreamBlock;
     408        pStreamBlock = NULL;
     409    }
     410}
     411
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r38294 r38395  
    108108 *
    109109 * @return  IPRT status code.
     110 * @param   pCallback
    110111 * @param   puContextID
    111  * @param   pCallbackData
    112112 */
    113 int Guest::callbackAdd(const PVBOXGUESTCTRL_CALLBACK pCallbackData, uint32_t *puContextID)
    114 {
    115     AssertPtrReturn(pCallbackData, VERR_INVALID_PARAMETER);
    116     AssertPtrReturn(puContextID, VERR_INVALID_PARAMETER);
     113int Guest::callbackAdd(const PVBOXGUESTCTRL_CALLBACK pCallback, uint32_t *puContextID)
     114{
     115    AssertPtrReturn(pCallback, VERR_INVALID_PARAMETER);
     116    /* puContextID is optional. */
    117117
    118118    int rc;
     
    142142
    143143        /* Add callback with new context ID to our callback map. */
    144         mCallbackMap[uNewContextID] = *pCallbackData;
     144        mCallbackMap[uNewContextID] = *pCallback;
    145145        Assert(mCallbackMap.size());
    146146
    147147        /* Report back new context ID. */
    148         *puContextID = uNewContextID;
     148        if (puContextID)
     149            *puContextID = uNewContextID;
    149150    }
    150151
     
    247248
    248249    return NULL;
     250}
     251
     252int Guest::callbackInit(PVBOXGUESTCTRL_CALLBACK pCallback, eVBoxGuestCtrlCallbackType enmType,
     253                        ComPtr<Progress> pProgress)
     254{
     255    AssertPtrReturn(pCallback, VERR_INVALID_POINTER);
     256    /* Everything else is optional. */
     257
     258    int rc = VINF_SUCCESS;
     259    switch (enmType)
     260    {
     261        case VBOXGUESTCTRLCALLBACKTYPE_EXEC_START:
     262        {
     263            PCALLBACKDATAEXECSTATUS pData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS));
     264            AssertPtrReturn(pData, VERR_NO_MEMORY);
     265            RT_BZERO(pData, sizeof(CALLBACKDATAEXECSTATUS));
     266            pCallback->cbData = sizeof(CALLBACKDATAEXECSTATUS);
     267            pCallback->pvData = pData;
     268            break;
     269        }
     270
     271        case VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT:
     272        {
     273            break;
     274        }
     275
     276        case VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS:
     277        {
     278
     279            break;
     280        }
     281
     282        default:
     283            rc = VERR_INVALID_PARAMETER;
     284            break;
     285    }
     286
     287    if (RT_SUCCESS(rc))
     288    {
     289        /* Init/set common stuff. */
     290        pCallback->mType  = enmType;
     291        pCallback->pProgress = pProgress;
     292    }
     293
     294    return rc;
    249295}
    250296
     
    475521}
    476522
     523/**
     524 * Waits for a callback (using its context ID) to complete.
     525 *
     526 * @return  IPRT status code.
     527 * @param   uContextID              Context ID to wait for.
     528 * @param   lStage                  Stage to wait for. Specify -1 if no staging is present/required.
     529 *                                  Specifying a stage is only needed if there's a multi operation progress
     530 *                                  object to wait for.
     531 * @param   lTimeout                Timeout (in ms) to wait for.
     532 */
    477533int Guest::callbackWaitForCompletion(uint32_t uContextID, LONG lStage, LONG lTimeout)
    478534{
     
    615671
    616672    uint32_t uContextID = pData->hdr.u32ContextID;
     673    Assert(uContextID);
    617674
    618675    /* Scope write locks as much as possible. */
     
    630687        }
    631688        else
    632             AssertReleaseMsgFailed(("Process status (PID=%u) does not have allocated callback data!\n",
    633                                     pData->u32PID));
     689            AssertReleaseMsgFailed(("Process status (PID=%u, CID=%u) does not have allocated callback data!\n",
     690                                    pData->u32PID, uContextID));
    634691    }
    635692
     
    813870        }
    814871        else
    815             AssertReleaseMsgFailed(("Process output status (PID=%u) does not have allocated callback data!\n",
    816                                     pData->u32PID));
     872            AssertReleaseMsgFailed(("Process output status (PID=%u, CID=%u) does not have allocated callback data!\n",
     873                                    pData->u32PID, uContextID));
    817874    }
    818875
     
    854911        }
    855912        else
    856             AssertReleaseMsgFailed(("Process input status (PID=%u) does not have allocated callback data!\n",
    857                                     pData->u32PID));
     913            AssertReleaseMsgFailed(("Process input status (PID=%u, CID=%u) does not have allocated callback data!\n",
     914                                    pData->u32PID, uContextID));
    858915    }
    859916
     
    10251082    ULONG uPID;
    10261083
    1027     HRESULT rc = this->ExecuteProcess(aTool,
    1028                                       ExecuteProcessFlag_Hidden,
    1029                                       ComSafeArrayInArg(aArguments),
    1030                                       ComSafeArrayInArg(aEnvironment),
    1031                                       aUsername, aPassword,
    1032                                       5 * 1000 /* Wait 5s for getting the process started. */,
    1033                                       &uPID, progressTool.asOutParam());
     1084    HRESULT rc = ExecuteProcess(aTool,
     1085                                ExecuteProcessFlag_Hidden,
     1086                                ComSafeArrayInArg(aArguments),
     1087                                ComSafeArrayInArg(aEnvironment),
     1088                                aUsername, aPassword,
     1089                                5 * 1000 /* Wait 5s for getting the process started. */,
     1090                                &uPID, progressTool.asOutParam());
    10341091    if (SUCCEEDED(rc))
    10351092    {
     
    10531110                if (SUCCEEDED(rc))
    10541111                {
    1055                     if (!uRetExitCode)
     1112                    if (uRetExitCode != 0) /* Not equal 0 means some error occured. */
    10561113                    {
     1114                        /** @todo IPRT exit code to string! */
    10571115                        rc = setError(VBOX_E_IPRT_ERROR,
    1058                                       tr("Error %u occurred while %s"),
    1059                                       uRetExitCode, Utf8Str(aDescription).c_str());
     1116                                      tr("%s: Error %u occured"),
     1117                                      Utf8Str(aDescription).c_str(), uRetExitCode);
    10601118                    }
    1061                     else
     1119                    else /* Return code 0, success. */
    10621120                    {
    10631121                        if (aProgress)
     
    10781136        }
    10791137        else
    1080             AssertReleaseMsgFailed(("Operation \"%s\" neither completed nor canceled!?\n",
     1138            AssertReleaseMsgFailed(("%s: Operation neither completed nor canceled!?\n",
    10811139                                    Utf8Str(aDescription).c_str()));
    10821140    }
     
    11711229
    11721230/**
    1173  * Gets the next stream block from a formerly processed guest stream. Will return
    1174  * E_UNEXPECTED if not enough guest stream data was read yet, otherwise S_OK or an appropriate
    1175  * error.
     1231 * TODO
    11761232 *
    11771233 * @return  HRESULT
    1178  * @param   aPID                    PID of process to get the next stream block from.
    1179  * @param   stream                  Reference to an already filled guest process stream.
    1180  * @param   streamBlock             Reference to a stream block which receives the parsed data.
     1234 * @param   aObjName
     1235 * @param   pStreamBlock
     1236 * @param   pObjInfo
     1237 * @param   enmAddAttribs
    11811238 */
    1182 HRESULT Guest::executeStreamCollectBlock(ULONG aPID,
    1183                                          GuestProcessStream &stream, GuestProcessStreamBlock &streamBlock)
    1184 {
     1239HRESULT Guest::executeStreamQueryFsObjInfo(IN_BSTR aObjName,
     1240                                           GuestProcessStreamBlock *pStreamBlock,
     1241                                           PRTFSOBJINFO pObjInfo,
     1242                                           RTFSOBJATTRADD enmAddAttribs)
     1243{
     1244    AssertPtrReturn(pStreamBlock, E_INVALIDARG);
     1245
    11851246    HRESULT rc = S_OK;
    1186 
    1187     SafeArray<BYTE> aOutputData;
    1188     ULONG cbOutputData = 0;
    1189     int vrc;
     1247    Utf8Str Utf8ObjName(aObjName);
     1248
     1249    int64_t iVal;
     1250    int vrc = pStreamBlock->GetInt64Ex("st_size", &iVal);
     1251    if (RT_SUCCESS(vrc))
     1252        pObjInfo->cbObject = iVal;
     1253    else
     1254        rc = setError(VBOX_E_IPRT_ERROR,
     1255                      tr("Unable to retrieve size for \"%s\" (%Rrc)"),
     1256                      Utf8ObjName.c_str(), vrc);
     1257    /** @todo Add more stuff! */
     1258    return rc;
     1259}
     1260
     1261/**
     1262 * Tries to drain the guest's output (from stdout) and fill it into
     1263 * a guest process stream object for later usage.
     1264 *
     1265 * @return  IPRT status code.
     1266 * @param   aPID                    PID of process to get the output from.
     1267 * @param   stream                  Reference to guest process stream to fill.
     1268 */
     1269int Guest::executeStreamDrain(ULONG aPID, GuestProcessStream &stream)
     1270{
     1271    AssertReturn(aPID, VERR_INVALID_PARAMETER);
     1272
     1273    /** @todo Should we try to drain the stream harder? */
     1274
     1275    int rc = VINF_SUCCESS;
    11901276    for (;;)
    11911277    {
    1192         rc = this->GetProcessOutput(aPID, ProcessOutputFlag_None,
    1193                                     10 * 1000 /* Timeout in ms */,
    1194                                     _64K, ComSafeArrayAsOutParam(aOutputData));
    1195         if (   SUCCEEDED(rc)
     1278        SafeArray<BYTE> aOutputData;
     1279        HRESULT hr = GetProcessOutput(aPID, ProcessOutputFlag_None /* Stdout */,
     1280                                      10 * 1000 /* Timeout in ms */,
     1281                                      _64K, ComSafeArrayAsOutParam(aOutputData));
     1282        if (   SUCCEEDED(hr)
    11961283            && aOutputData.size())
    11971284        {
    1198             vrc = stream.AddData(aOutputData.raw(), aOutputData.size());
    1199             if (RT_UNLIKELY(RT_FAILURE(vrc)))
    1200             {
    1201                 rc = setError(VBOX_E_IPRT_ERROR,
    1202                               tr("Error while adding guest output to stream buffer (%Rrc)"), vrc);
     1285            rc = stream.AddData(aOutputData.raw(), aOutputData.size());
     1286            if (RT_UNLIKELY(RT_FAILURE(rc)))
    12031287                break;
    1204             }
    1205             else
    1206             {
    1207                 /* Try to parse the stream output we gathered until now. If we still need more
    1208                  * data the parsing routine will tell us and we just do another poll round. */
    1209                 vrc = stream.ParseBlock(streamBlock);
    1210                 if (RT_SUCCESS(vrc))
    1211                 {
    1212                     /* Yay, we're done! */
    1213                     break;
    1214                 }
    1215                 else if (vrc == VERR_MORE_DATA)
    1216                 {
    1217                     /* We need another poll round. */
    1218                     continue;
    1219                 }
    1220                 else
    1221                     rc = setError(VBOX_E_IPRT_ERROR,
    1222                                   tr("Error while parsing guest output (%Rrc)"), vrc);
    1223             }
    1224         }
    1225         else /* No more output! */
    1226         {
    1227             if (vrc == VERR_MORE_DATA)
    1228                 rc = E_UNEXPECTED; /** @todo Find a better rc! */
     1288        }
     1289        else /* No more output and/or error! */
    12291290            break;
    1230         }
    1231     }
     1291    }
     1292
     1293    return rc;
     1294}
     1295
     1296/**
     1297 * Frees a guest stream objects vector.
     1298 *
     1299 * @param   streamObjects           Vector to free.
     1300 */
     1301void Guest::executeStreamFree(GuestCtrlStreamObjects &streamObjects)
     1302{
     1303    for (GuestCtrlStreamObjectsIter it = streamObjects.begin();
     1304         it != streamObjects.end(); it++)
     1305    {
     1306        executeStreamFreeBlock(*it);
     1307    }
     1308    streamObjects.clear();
     1309}
     1310
     1311/**
     1312 * Frees a guest stream block. Pure convenience function for
     1313 * GuestProcessStream::FreeBlock().
     1314 *
     1315 * @return  IPRT status code.
     1316 * @param   pBlock
     1317 */
     1318void Guest::executeStreamFreeBlock(GuestProcessStreamBlock *pBlock)
     1319{
     1320    GuestProcessStream::FreeBlock(pBlock);
     1321}
     1322
     1323/**
     1324 * Tries to get the next upcoming value block from a started guest process
     1325 * by first draining its output and then processing the received guest stream.
     1326 *
     1327 * @return  IPRT status code.
     1328 * @param   aPID                    PID of process to get/parse the output from.
     1329 * @param   stream                  Reference to process stream object to use.
     1330 * @param   streamBlock             Reference that receives the next stream block data.
     1331 *
     1332 */
     1333int Guest::executeStreamGetNextBlock(ULONG aPID, GuestProcessStream &stream,
     1334                                     GuestProcessStreamBlock &streamBlock)
     1335{
     1336    int rc = executeStreamDrain(aPID, stream);
     1337    if (RT_SUCCESS(rc))
     1338        rc = stream.ParseBlock(streamBlock);
    12321339
    12331340    return rc;
     
    12441351 *                                  storing the parsed data.
    12451352 */
    1246 HRESULT Guest::executeStreamCollectOutput(ULONG aPID, GuestCtrlStreamObjects &streamObjects)
    1247 {
    1248     HRESULT rc = S_OK;
    1249 
    1250     SafeArray<BYTE> aOutputData;
    1251     ULONG cbOutputData = 0;
     1353HRESULT Guest::executeStreamParse(ULONG aPID, GuestCtrlStreamObjects &streamObjects)
     1354{
    12521355    GuestProcessStream guestStream;
    1253 
    1254     for (;;)
    1255     {
    1256         rc = this->GetProcessOutput(aPID, ProcessOutputFlag_None,
    1257                                     10 * 1000 /* Timeout in ms */,
    1258                                     _64K, ComSafeArrayAsOutParam(aOutputData));
    1259         if (   SUCCEEDED(rc)
    1260             && aOutputData.size())
    1261         {
    1262             int vrc = guestStream.AddData(aOutputData.raw(), aOutputData.size());
    1263             if (RT_UNLIKELY(RT_FAILURE(vrc)))
    1264             {
    1265                 rc = setError(VBOX_E_IPRT_ERROR,
    1266                               tr("Error while adding guest output to stream buffer (%Rrc)"), vrc);
     1356    HRESULT hr = executeStreamDrain(aPID, guestStream);
     1357    if (SUCCEEDED(hr))
     1358    {
     1359        for (;;)
     1360        {
     1361            /* Try to parse the stream output we gathered until now. If we still need more
     1362             * data the parsing routine will tell us and we just do another poll round. */
     1363            GuestProcessStreamBlock *pCurBlock = (GuestProcessStreamBlock*)
     1364                                            RTMemAlloc(sizeof(GuestProcessStreamBlock));
     1365            if (!pCurBlock)
     1366            {
     1367                hr = setError(VBOX_E_IPRT_ERROR,
     1368                              tr("No memory for allocating stream block"));
    12671369                break;
    12681370            }
    1269         }
    1270         else /* No more output! */
    1271             break;
    1272     }
    1273 
    1274     if (SUCCEEDED(rc))
    1275     {
    1276         for (;;)
    1277         {
    1278             GuestProcessStreamBlock curBlock;
    1279             rc = executeStreamCollectBlock(aPID,
    1280                                            guestStream, curBlock);
    1281             if (SUCCEEDED(rc))
    1282 
    1283             {
    1284                 if (curBlock.GetCount())
    1285                     streamObjects.push_back(curBlock);
     1371            int vrc = guestStream.ParseBlock(*pCurBlock);
     1372            if (RT_SUCCESS(vrc))
     1373            {
     1374                if (pCurBlock->GetCount())
     1375                {
     1376                    streamObjects.push_back(pCurBlock);
     1377                }
    12861378                else
     1379                {
     1380                    GuestProcessStream::FreeBlock(pCurBlock);
    12871381                    break; /* No more data. */
    1288             }
    1289             else
    1290             {
    1291                 rc = setError(VBOX_E_IPRT_ERROR,
    1292                               tr("Error while parsing guest stream block"));
    1293                 break;
    1294             }
    1295         }
    1296     }
    1297 
    1298     return rc;
     1382                }
     1383            }
     1384            else /* Everything else would be an error! */
     1385                hr = setError(VBOX_E_IPRT_ERROR,
     1386                              tr("Error while parsing guest output (%Rrc)"), vrc);
     1387        }
     1388    }
     1389
     1390    /** @todo Add check if there now are any sream objects at all! */
     1391
     1392    return hr;
    12991393}
    13001394
     
    14711565                if (RT_SUCCESS(vrc))
    14721566                {
    1473                     /* Allocate payload. */
    1474                     PCALLBACKDATAEXECSTATUS pStatus = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(sizeof(CALLBACKDATAEXECSTATUS));
    1475                     AssertReturn(pStatus, VBOX_E_IPRT_ERROR);
    1476                     RT_ZERO(*pStatus);
    1477 
    1478                     /* Create callback. */
    14791567                    VBOXGUESTCTRL_CALLBACK callback;
    1480                     callback.mType  = VBOXGUESTCTRLCALLBACKTYPE_EXEC_START;
    1481                     callback.cbData = sizeof(CALLBACKDATAEXECSTATUS);
    1482                     callback.pvData = pStatus;
    1483                     callback.pProgress = pProgress;
    1484 
    1485                     vrc = callbackAdd(&callback, &uContextID);
     1568                    vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_START, pProgress);
     1569                    if (RT_SUCCESS(vrc))
     1570                    {
     1571                        /* Allocate and assign payload. */
     1572                        callback.cbData = sizeof(CALLBACKDATAEXECSTATUS);
     1573                        PCALLBACKDATAEXECSTATUS pData = (PCALLBACKDATAEXECSTATUS)RTMemAlloc(callback.cbData);
     1574                        AssertReturn(pData, E_OUTOFMEMORY);
     1575                        RT_BZERO(pData, callback.cbData);
     1576                        callback.pvData = pData;
     1577                    }
     1578
     1579                    if (RT_SUCCESS(vrc))
     1580                        vrc = callbackAdd(&callback, &uContextID);
     1581
    14861582                    if (RT_SUCCESS(vrc))
    14871583                    {
     
    16691765                aTimeoutMS = UINT32_MAX;
    16701766
    1671             /* Construct callback data. */
    16721767            VBOXGUESTCTRL_CALLBACK callback;
    1673             callback.mType  = VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS;
    1674             callback.cbData = sizeof(CALLBACKDATAEXECINSTATUS);
    1675 
    1676             PCALLBACKDATAEXECINSTATUS pStatus = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(callback.cbData);
    1677             AssertReturn(pStatus, VBOX_E_IPRT_ERROR);
    1678             RT_ZERO(*pStatus);
    1679 
    1680             /* Save PID + output flags for later use. */
    1681             pStatus->u32PID = aPID;
    1682             pStatus->u32Flags = aFlags;
    1683 
    1684             callback.pvData = pStatus;
    1685             callback.pProgress = pProgress;
    1686 
    1687             /* Add the callback. */
    1688             vrc = callbackAdd(&callback, &uContextID);
     1768            vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_INPUT_STATUS, pProgress);
     1769            if (RT_SUCCESS(vrc))
     1770            {
     1771                callback.cbData = sizeof(CALLBACKDATAEXECINSTATUS);
     1772                PCALLBACKDATAEXECINSTATUS pData = (PCALLBACKDATAEXECINSTATUS)RTMemAlloc(callback.cbData);
     1773                AssertReturn(pData, E_OUTOFMEMORY);
     1774                RT_BZERO(pData, callback.cbData);
     1775                callback.pvData = pData;
     1776
     1777                /* Save PID + output flags for later use. */
     1778                pData->u32PID = aPID;
     1779                pData->u32Flags = aFlags;
     1780            }
     1781
     1782            if (RT_SUCCESS(vrc))
     1783                vrc = callbackAdd(&callback, &uContextID);
     1784
    16891785            if (RT_SUCCESS(vrc))
    16901786            {
     
    18251921        if (RT_FAILURE(vrc))
    18261922            rc = setError(VBOX_E_IPRT_ERROR,
    1827                           Guest::tr("Cannot get output from non-existent process (PID %u)"), aPID);
     1923                          Guest::tr("Cannot get output from non-existent guest process (PID %u)"), aPID);
    18281924
    18291925        if (SUCCEEDED(rc))
     
    18421938            {
    18431939                rc = pProgress->init(static_cast<IGuest*>(this),
    1844                                      Bstr(tr("Setting input for process")).raw(),
     1940                                     Bstr(tr("Getting output for guest process")).raw(),
    18451941                                     TRUE /* Cancelable */);
    18461942            }
     
    18571953                uHandleID = OUTPUT_HANDLE_ID_STDERR;
    18581954
    1859             /* Construct callback data. */
    18601955            VBOXGUESTCTRL_CALLBACK callback;
    1861             callback.mType  = VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT;
    1862             callback.cbData = sizeof(CALLBACKDATAEXECOUT);
    1863 
    1864             PCALLBACKDATAEXECOUT pStatus = (PCALLBACKDATAEXECOUT)RTMemAlloc(callback.cbData);
    1865             AssertReturn(pStatus, VBOX_E_IPRT_ERROR);
    1866             RT_ZERO(*pStatus);
    1867 
    1868             /* Save PID + output flags for later use. */
    1869             pStatus->u32PID = aPID;
    1870             pStatus->u32Flags = aFlags;
    1871 
    1872             callback.pvData = pStatus;
    1873             callback.pProgress = pProgress;
    1874 
    1875             /* Add the callback. */
    1876             vrc = callbackAdd(&callback, &uContextID);
     1956            vrc = callbackInit(&callback, VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT, pProgress);
     1957            if (RT_SUCCESS(vrc))
     1958            {
     1959                callback.cbData = sizeof(CALLBACKDATAEXECOUT);
     1960                PCALLBACKDATAEXECOUT pData = (PCALLBACKDATAEXECOUT)RTMemAlloc(callback.cbData);
     1961                AssertReturn(pData, E_OUTOFMEMORY);
     1962                RT_BZERO(pData, callback.cbData);
     1963                callback.pvData = pData;
     1964
     1965                /* Save PID + output flags for later use. */
     1966                pData->u32PID = aPID;
     1967                pData->u32Flags = aFlags;
     1968            }
     1969
     1970            if (RT_SUCCESS(vrc))
     1971                vrc = callbackAdd(&callback, &uContextID);
     1972
    18771973            if (RT_SUCCESS(vrc))
    18781974            {
     
    19162012                PCALLBACKDATAEXECOUT pExecOut = NULL;
    19172013
    1918                  /*
    1919                  * Wait for the first stage (=0) to complete (that is starting the process).
     2014                /*
     2015                 * Wait for the first output callback notification to arrive.
    19202016                 */
    1921                 vrc = callbackWaitForCompletion(uContextID, 0 /* Stage */, aTimeoutMS);
     2017                vrc = callbackWaitForCompletion(uContextID, -1 /* No staging */, aTimeoutMS);
    19222018                if (RT_SUCCESS(vrc))
    19232019                {
     
    19612057                rc = handleErrorHGCM(vrc);
    19622058
    1963             if (SUCCEEDED(rc))
    1964             {
    1965 
    1966             }
    1967 
    19682059            /* The callback isn't needed anymore -- just was kept locally. */
    19692060            callbackDestroy(uContextID);
  • trunk/src/VBox/Main/src-client/GuestCtrlImplDir.cpp

    r38290 r38395  
    138138 *
    139139 * @return IPRT status code.
    140  * @param puHandle             Pointer where the handle gets stored to.
     140 * @param puHandle             Pointer where the handle gets stored to. Optional.
    141141 * @param uPID                 PID of guest process running the associated "vbox_ls".
    142  * @param pszDirectory         Directory the handle is assigned to.
    143  * @param pszFilter            Directory filter.  Optional.
     142 * @param aDirectory           Directory the handle is assigned to.
     143 * @param aFilter              Directory filter.  Optional.
    144144 * @param uFlags               Directory open flags.
    145145 *
    146146 */
    147147int Guest::directoryCreateHandle(ULONG *puHandle, ULONG uPID,
    148                                  const char *pszDirectory, const char *pszFilter, ULONG uFlags)
    149 {
    150     AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
    151     AssertPtrReturn(pszDirectory, VERR_INVALID_POINTER);
    152     /* pszFilter is optional. */
     148                                 IN_BSTR aDirectory, IN_BSTR aFilter, ULONG uFlags)
     149{
     150    AssertReturn(uPID, VERR_INVALID_PARAMETER);
     151    CheckComArgStrNotEmptyOrNull(aDirectory);
     152    /* aFilter is optional. */
     153    /* uFlags are optional. */
    153154
    154155    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     
    160161        uint32_t uHandleTry = ASMAtomicIncU32(&mNextDirectoryID);
    161162        GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandleTry);
    162         if (it == mGuestDirectoryMap.end())
    163         {
     163        if (it == mGuestDirectoryMap.end()) /* We found a free slot ... */
     164        {
     165            mGuestDirectoryMap[uHandleTry].mDirectory = aDirectory;
     166            mGuestDirectoryMap[uHandleTry].mFilter = aFilter;
     167            mGuestDirectoryMap[uHandleTry].mPID = uPID;
     168            mGuestDirectoryMap[uHandleTry].mFlags = uFlags;
     169            Assert(mGuestDirectoryMap.size());
     170
    164171            rc = VINF_SUCCESS;
    165             if (!RTStrAPrintf(&mGuestDirectoryMap[uHandleTry].mpszDirectory, pszDirectory))
    166                 rc = VERR_NO_MEMORY;
    167             else
    168             {
    169                 /* Filter is optional. */
    170                 if (pszFilter)
    171                 {
    172                     if (!RTStrAPrintf(&mGuestDirectoryMap[uHandleTry].mpszFilter, pszFilter))
    173                         rc = VERR_NO_MEMORY;
    174                 }
    175 
    176                 if (RT_SUCCESS(rc))
    177                 {
    178                     mGuestDirectoryMap[uHandleTry].mPID = uPID;
    179                     mGuestDirectoryMap[uHandleTry].mFlags = uFlags;
    180                     *puHandle = uHandleTry;
    181 
    182                     break;
    183                 }
    184             }
    185 
    186             if (RT_FAILURE(rc))
    187                 break;
    188 
    189             Assert(mGuestDirectoryMap.size());
     172
     173            if (puHandle)
     174                *puHandle = uHandleTry;
     175            break;
    190176        }
    191177    }
     
    208194    if (it != mGuestDirectoryMap.end())
    209195    {
    210         RTStrFree(it->second.mpszDirectory);
    211         RTStrFree(it->second.mpszFilter);
    212 
    213196        /* Destroy raw guest stream buffer - not used
    214197         * anymore. */
     
    220203}
    221204
     205STDMETHODIMP Guest::DirectoryExists(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
     206{
     207#ifndef VBOX_WITH_GUEST_CONTROL
     208    ReturnComNotImplemented();
     209#else /* VBOX_WITH_GUEST_CONTROL */
     210    using namespace guestControl;
     211
     212    CheckComArgStrNotEmptyOrNull(aDirectory);
     213
     214    /* Do not allow anonymous executions (with system rights). */
     215    if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
     216        return setError(E_INVALIDARG, tr("No user name specified"));
     217
     218    return directoryExistsInternal(aDirectory,
     219                                   aUsername, aPassword, aExists);
     220#endif
     221}
     222
     223#ifdef VBOX_WITH_GUEST_CONTROL
     224HRESULT Guest::directoryExistsInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
     225{
     226    using namespace guestControl;
     227
     228    CheckComArgStrNotEmptyOrNull(aDirectory);
     229
     230    AutoCaller autoCaller(this);
     231    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     232
     233    RTFSOBJINFO objInfo;
     234    int rc;
     235    HRESULT hr = directoryQueryInfoInternal(aDirectory,
     236                                            aUsername, aPassword,
     237                                            &objInfo, RTFSOBJATTRADD_NOTHING, &rc);
     238    if (SUCCEEDED(hr))
     239    {
     240        switch (rc)
     241        {
     242            case VINF_SUCCESS:
     243                *aExists = TRUE;
     244                break;
     245
     246            case VERR_FILE_NOT_FOUND:
     247                *aExists = FALSE;
     248                break;
     249
     250            case VERR_NOT_FOUND:
     251                rc = setError(VBOX_E_IPRT_ERROR,
     252                              Guest::tr("Unable to query directory existence"));
     253                break;
     254
     255            default:
     256                AssertReleaseMsgFailed(("directoryExistsInternal: Unknown return value (%Rrc)\n", rc));
     257                break;
     258        }
     259    }
     260    return hr;
     261}
     262#endif
     263
    222264/**
    223265 * Gets the associated PID from a directory handle.
    224266 *
    225  * @return  uint32_t            Associated PID, 0 if handle not found/invalid.
    226  * @param   uHandle             Directory handle to get PID for.
     267 * @return  uint32_t                Associated PID, 0 if handle not found/invalid.
     268 * @param   uHandle                 Directory handle to get PID for.
    227269 */
    228270uint32_t Guest::directoryGetPID(uint32_t uHandle)
     
    237279}
    238280
     281/**
     282 * Returns the next directory entry of an open guest directory.
     283 * Returns VERR_NO_MORE_FILES if no more entries available.
     284 *
     285 * @return  IPRT status code.
     286 * @param   uHandle                 Directory handle to get entry for.
     287 * @param   streamBlock             Reference that receives the next stream block data.
     288 */
    239289int Guest::directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock)
    240290{
    241     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     291    // LOCK DOES NOT WORK HERE!?
     292    //AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    242293
    243294    GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
    244295    if (it != mGuestDirectoryMap.end())
    245296    {
    246         HRESULT hr = executeStreamCollectBlock(it->second.mPID,
    247                                                it->second.mStream, streamBlock);
    248         if (FAILED(hr))
    249             return VERR_INVALID_PARAMETER; /** @todo Find better rc! */
    250 
    251         return VINF_SUCCESS;
     297        return executeStreamGetNextBlock(it->second.mPID,
     298                                         it->second.mStream, streamBlock);
    252299    }
    253300
     
    259306 * or not.
    260307 *
    261  * @return  bool                True if handle exists, false if not.
    262  * @param   uHandle             Directory handle to check.
     308 * @return  bool                    True if handle exists, false if not.
     309 * @param   uHandle                 Directory handle to check.
    263310 */
    264311bool Guest::directoryHandleExists(uint32_t uHandle)
     
    315362        return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
    316363
    317     HRESULT rc = S_OK;
     364    HRESULT hr = S_OK;
    318365    try
    319366    {
     
    354401
    355402        ULONG uPID;
    356         rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_LS).raw(), Bstr("Opening directory").raw(),
     403        /** @todo Don't wait for tool to finish! Might take a lot of time! */
     404        hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_LS).raw(), Bstr("Opening directory").raw(),
    357405                                   ComSafeArrayAsInParam(args),
    358406                                   ComSafeArrayAsInParam(env),
    359407                                   aUsername, aPassword,
    360408                                   NULL /* Progress */, &uPID);
    361         if (SUCCEEDED(rc))
     409        if (SUCCEEDED(hr))
    362410        {
    363411            /* Assign new directory handle ID. */
    364             int vrc = directoryCreateHandle(aHandle, uPID,
    365                                             Utf8Directory.c_str(),
    366                                             Utf8Filter.isEmpty() ? NULL : Utf8Filter.c_str(),
    367                                             aFlags);
    368             if (RT_FAILURE(vrc))
    369                 rc = setError(VBOX_E_IPRT_ERROR,
     412            ULONG uHandleNew;
     413            int vrc = directoryCreateHandle(&uHandleNew, uPID,
     414                                            aDirectory, aFilter, aFlags);
     415            if (RT_SUCCESS(vrc))
     416            {
     417                *aHandle = uHandleNew;
     418            }
     419            else
     420                hr = setError(VBOX_E_IPRT_ERROR,
    370421                              tr("Unable to create guest directory handle (%Rrc)"), vrc);
    371422        }
     
    373424    catch (std::bad_alloc &)
    374425    {
    375         rc = E_OUTOFMEMORY;
    376     }
    377     return rc;
     426        hr = E_OUTOFMEMORY;
     427    }
     428    return hr;
     429}
     430
     431HRESULT Guest::directoryQueryInfoInternal(IN_BSTR aDirectory,
     432                                          IN_BSTR aUsername, IN_BSTR aPassword,
     433                                          PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs,
     434                                          int *pRC)
     435{
     436    using namespace guestControl;
     437
     438    /** @todo Search directory cache first? */
     439
     440    CheckComArgStrNotEmptyOrNull(aDirectory);
     441    /* aUsername is optional. */
     442    /* aPassword is optional. */
     443    /* aObjInfo is optional. */
     444
     445    AutoCaller autoCaller(this);
     446    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     447
     448    HRESULT hr = S_OK;
     449    try
     450    {
     451        Utf8Str Utf8Dir(aDirectory);
     452        Utf8Str Utf8Username(aUsername);
     453        Utf8Str Utf8Password(aPassword);
     454
     455        com::SafeArray<IN_BSTR> args;
     456        com::SafeArray<IN_BSTR> env;
     457
     458        /*
     459         * Prepare tool command line.
     460         */
     461
     462        /* We need to get output which is machine-readable in form
     463         * of "key=value\0..key=value\0\0". */
     464        args.push_back(Bstr("--machinereadable").raw());
     465
     466        /* Only the actual file name to chekc is needed for now. */
     467        args.push_back(Bstr(Utf8Dir).raw());
     468
     469        /*
     470         * Execute guest process.
     471         */
     472        ULONG uPID;
     473        hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying directory information").raw(),
     474                                   ComSafeArrayAsInParam(args),
     475                                   ComSafeArrayAsInParam(env),
     476                                   aUsername, aPassword,
     477                                   NULL /* Progress */, &uPID);
     478        if (SUCCEEDED(hr))
     479        {
     480            GuestCtrlStreamObjects streamObjs;
     481            hr = executeStreamParse(uPID, streamObjs);
     482            if (SUCCEEDED(hr))
     483            {
     484                int rc = VINF_SUCCESS;
     485
     486                GuestProcessStreamBlock *pBlock = streamObjs[0];
     487                AssertPtr(pBlock);
     488                const char *pszFsType = pBlock->GetString("ftype");
     489                if (!pszFsType) /* Attribute missing? */
     490                     rc = VERR_NOT_FOUND;
     491                if (   RT_SUCCESS(rc)
     492                    && strcmp(pszFsType, "d")) /* Directory? */
     493                {
     494                     rc = VERR_FILE_NOT_FOUND;
     495                }
     496                if (   RT_SUCCESS(rc)
     497                    && aObjInfo) /* Do we want object details? */
     498                {
     499                    hr = executeStreamQueryFsObjInfo(aDirectory, pBlock,
     500                                                     aObjInfo, enmAddAttribs);
     501                }
     502
     503                executeStreamFree(streamObjs);
     504
     505                if (pRC)
     506                    *pRC = rc;
     507            }
     508        }
     509    }
     510    catch (std::bad_alloc &)
     511    {
     512        hr = E_OUTOFMEMORY;
     513    }
     514    return hr;
    378515}
    379516#endif /* VBOX_WITH_GUEST_CONTROL */
     
    391528    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    392529
    393     HRESULT rc = S_OK;
     530    HRESULT hr = S_OK;
    394531    try
    395532    {
    396533        GuestProcessStreamBlock streamBlock;
    397         int vrc = directoryGetNextEntry(aHandle, streamBlock);
    398         if (RT_SUCCESS(vrc))
     534        int rc = directoryGetNextEntry(aHandle, streamBlock);
     535        if (RT_SUCCESS(rc))
    399536        {
    400537            ComObjPtr <GuestDirEntry> pDirEntry;
    401             rc = pDirEntry.createObject();
    402             ComAssertComRC(rc);
    403 
    404             rc = pDirEntry->init(this, streamBlock);
    405             if (SUCCEEDED(rc))
     538            hr = pDirEntry.createObject();
     539            ComAssertComRC(hr);
     540
     541            hr = pDirEntry->init(this, streamBlock);
     542            if (SUCCEEDED(hr))
    406543            {
    407544                pDirEntry.queryInterfaceTo(aDirEntry);
    408545            }
    409546            else
    410                 rc = setError(VBOX_E_IPRT_ERROR,
     547                hr = setError(VBOX_E_IPRT_ERROR,
    411548                              Guest::tr("Unable to init guest directory entry"));
    412549        }
     550        else if (rc == VERR_NO_MORE_FILES)
     551        {
     552            /* No more directory entries to read. */
     553            hr = E_ABORT; /** @todo Find/define a better rc! */
     554        }
    413555        else
    414             rc = setError(VBOX_E_IPRT_ERROR,
    415                           Guest::tr("Directory handle is invalid"));
     556            hr = setError(VBOX_E_IPRT_ERROR,
     557                          Guest::tr("Failed getting next directory entry (%Rrc)"), rc);
    416558    }
    417559    catch (std::bad_alloc &)
    418560    {
    419         rc = E_OUTOFMEMORY;
    420     }
    421     return rc;
    422 #endif
    423 }
    424 
     561        hr = E_OUTOFMEMORY;
     562    }
     563    return hr;
     564#endif
     565}
     566
  • trunk/src/VBox/Main/src-client/GuestCtrlImplFile.cpp

    r38290 r38395  
    4747
    4848    return fileExistsInternal(aFile,
    49                               aUsername, aPassword, aExists,
    50                               NULL /* rc */);
     49                              aUsername, aPassword, aExists);
    5150#endif
    5251}
    5352
    5453#ifdef VBOX_WITH_GUEST_CONTROL
    55 HRESULT Guest::fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists, int *pRC)
     54HRESULT Guest::fileExistsInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
    5655{
    5756    using namespace guestControl;
     
    6261    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    6362
    64     HRESULT rc = S_OK;
     63    RTFSOBJINFO objInfo;
     64    int rc;
     65    HRESULT hr = fileQueryInfoInternal(aFile,
     66                                       aUsername, aPassword,
     67                                       &objInfo, RTFSOBJATTRADD_NOTHING, &rc);
     68    if (SUCCEEDED(hr))
     69    {
     70        switch (rc)
     71        {
     72            case VINF_SUCCESS:
     73                *aExists = TRUE;
     74                break;
     75
     76            case VERR_FILE_NOT_FOUND:
     77                *aExists = FALSE;
     78                break;
     79
     80            case VERR_NOT_FOUND:
     81                rc = setError(VBOX_E_IPRT_ERROR,
     82                              Guest::tr("Unable to query file existence"));
     83                break;
     84
     85            default:
     86                AssertReleaseMsgFailed(("fileExistsInternal: Unknown return value (%Rrc)\n", rc));
     87                break;
     88        }
     89    }
     90    return hr;
     91}
     92
     93HRESULT Guest::fileQueryInfoInternal(IN_BSTR aFile,
     94                                     IN_BSTR aUsername, IN_BSTR aPassword,
     95                                     PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs,
     96                                     int *pRC)
     97{
     98    using namespace guestControl;
     99
     100    /* aUsername is optional. */
     101    /* aPassword is optional. */
     102    /* aObjInfo is optional. */
     103
     104    HRESULT hr;
    65105    try
    66106    {
     
    86126         * Execute guest process.
    87127         */
    88         rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Checking for file existence").raw(),
     128        ULONG uPID;
     129        hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying file information").raw(),
    89130                                   ComSafeArrayAsInParam(args),
    90131                                   ComSafeArrayAsInParam(env),
    91132                                   aUsername, aPassword,
    92                                    NULL /* Progress */, NULL /* PID */);
    93 
    94         /* If the call succeeded the file exists, otherwise it does not. */
    95         *aExists = SUCCEEDED(rc) ? TRUE : FALSE;
     133                                   NULL /* Progress */, &uPID);
     134        if (SUCCEEDED(hr))
     135        {
     136            GuestCtrlStreamObjects streamObjs;
     137            hr = executeStreamParse(uPID, streamObjs);
     138            if (SUCCEEDED(hr))
     139            {
     140                int rc = VINF_SUCCESS;
     141
     142                GuestProcessStreamBlock *pBlock = streamObjs[0];
     143                AssertPtr(pBlock);
     144                const char *pszFsType = pBlock->GetString("ftype");
     145                if (!pszFsType) /* Attribute missing? */
     146                     rc = VERR_NOT_FOUND;
     147                if (   RT_SUCCESS(rc)
     148                    && strcmp(pszFsType, "-")) /* Regular file? */
     149                {
     150                     rc = VERR_FILE_NOT_FOUND;
     151                }
     152                if (   RT_SUCCESS(rc)
     153                    && aObjInfo) /* Do we want object details? */
     154                {
     155                    hr = executeStreamQueryFsObjInfo(aFile, pBlock,
     156                                                     aObjInfo, enmAddAttribs);
     157                }
     158
     159                executeStreamFree(streamObjs);
     160
     161                if (pRC)
     162                    *pRC = rc;
     163            }
     164        }
    96165    }
    97166    catch (std::bad_alloc &)
    98167    {
    99         rc = E_OUTOFMEMORY;
    100     }
    101     return rc;
     168        hr = E_OUTOFMEMORY;
     169    }
     170
     171    return hr;
    102172}
    103173#endif /* VBOX_WITH_GUEST_CONTROL */
     
    116186        return setError(E_INVALIDARG, tr("No user name specified"));
    117187
    118     return fileQuerySizeInternal(aFile,
    119                                  aUsername, aPassword, aSize,
    120                                  NULL /* rc */);
    121 #endif
    122 }
    123 
    124 #ifdef VBOX_WITH_GUEST_CONTROL
    125 HRESULT Guest::fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize, int *pRC)
    126 {
    127     using namespace guestControl;
    128 
    129     CheckComArgStrNotEmptyOrNull(aFile);
    130 
    131188    AutoCaller autoCaller(this);
    132189    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    133190
    134     HRESULT rc = S_OK;
    135     try
    136     {
    137         Utf8Str Utf8File(aFile);
    138         Utf8Str Utf8Username(aUsername);
    139         Utf8Str Utf8Password(aPassword);
    140 
    141         com::SafeArray<IN_BSTR> args;
    142         com::SafeArray<IN_BSTR> env;
    143 
    144         /*
    145          * Prepare tool command line.
    146          */
    147 
    148         /* We need to get output which is machine-readable in form
    149          * of "key=value\0..key=value\0\0". */
    150         args.push_back(Bstr("--machinereadable").raw());
    151 
    152         /* Only the actual file name to chekc is needed for now. */
    153         args.push_back(Bstr(Utf8File).raw());
    154 
    155         /*
    156          * Execute guest process.
    157          */
    158         ComPtr<IProgress> progressFileSize;
    159         ULONG uPID;
    160 
    161         rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying file size").raw(),
    162                                    ComSafeArrayAsInParam(args),
    163                                    ComSafeArrayAsInParam(env),
    164                                    aUsername, aPassword,
    165                                    progressFileSize.asOutParam(), &uPID);
    166         if (SUCCEEDED(rc))
     191    return fileQuerySizeInternal(aFile,
     192                                 aUsername, aPassword, aSize);
     193#endif
     194}
     195
     196#ifdef VBOX_WITH_GUEST_CONTROL
     197HRESULT Guest::fileQuerySizeInternal(IN_BSTR aFile, IN_BSTR aUsername, IN_BSTR aPassword, LONG64 *aSize)
     198{
     199    using namespace guestControl;
     200
     201    CheckComArgStrNotEmptyOrNull(aFile);
     202
     203    int rc;
     204    RTFSOBJINFO objInfo;
     205    HRESULT hr = fileQueryInfoInternal(aFile,
     206                                       aUsername, aPassword,
     207                                       &objInfo, RTFSOBJATTRADD_NOTHING, &rc);
     208    if (SUCCEEDED(hr))
     209    {
     210        switch (rc)
    167211        {
    168             GuestCtrlStreamObjects streamObjs;
    169             rc = executeStreamCollectOutput(uPID, streamObjs);
    170             if (SUCCEEDED(rc))
    171             {
    172                 /** @todo */
    173                 #if 0
    174                                                     int64_t iVal;
    175                                     vrc = guestStream.GetInt64Ex("st_size", &iVal);
    176                                     if (RT_SUCCESS(vrc))
    177                                         *aSize = iVal;
    178                                     else
    179                                         rc = setError(VBOX_E_IPRT_ERROR,
    180                                                       tr("Query file size: Unable to retrieve file size for file \"%s\" (%Rrc)"),
    181                                                       Utf8File.c_str(), vrc);
    182               #endif
    183             }
     212            case VINF_SUCCESS:
     213                *aSize = objInfo.cbObject;
     214                break;
     215
     216            case VERR_FILE_NOT_FOUND:
     217                rc = setError(VBOX_E_IPRT_ERROR,
     218                              Guest::tr("File not found"));
     219                break;
     220
     221            case VERR_NOT_FOUND:
     222                rc = setError(VBOX_E_IPRT_ERROR,
     223                              Guest::tr("Unable to query file size"));
     224                break;
     225
     226            default:
     227                AssertReleaseMsgFailed(("fileExistsInternal: Unknown return value (%Rrc)\n", rc));
     228                break;
    184229        }
    185230    }
    186     catch (std::bad_alloc &)
    187     {
    188         rc = E_OUTOFMEMORY;
    189     }
    190231    return rc;
    191232}
  • trunk/src/VBox/Main/src-client/GuestDirEntryImpl.cpp

    r38296 r38395  
    5959
    6060    mData.mNodeId = streamBlock.GetInt64("node_id");
    61     mData.mName =  BstrFmt("%s", streamBlock.GetString("name"));
     61    const char *pszName = streamBlock.GetString("name");
     62    if (pszName)
     63        mData.mName =  BstrFmt("%s", pszName);
    6264    mData.mType = GuestDirEntry::fileTypeToEntryType(streamBlock.GetString("ftype"));
    6365
  • trunk/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp

    r38269 r38395  
    5858} aTests[] =
    5959{
     60    /*
     61     * Single object parsing.
     62     * An object is represented by one or multiple key=value pairs which are
     63     * separated by a single "\0". If this termination is missing it will be assumed
     64     * that we need to collect more data to do a successful parsing.
     65     */
     66
    6067    /* Invalid stuff. */
    6168    { NULL,                             0,                                                 0,  0,                                         0, VERR_INVALID_POINTER },
     
    6673    { "foo=bar2",                       0,                                                 50, 50,                                        0, VERR_INVALID_PARAMETER },
    6774    /* Empty buffers. */
    68     { "",                               1,                                                 0,  1,                                         0, VERR_MORE_DATA },
    69     { "\0",                             1,                                                 0,  1,                                         0, VERR_MORE_DATA },
    70     /* Incomplete buffer (missing components). */
    71     { szUnterm1,                        5,                                                 0,  0,                                         0, VERR_MORE_DATA },
    72     { "foo1",                           sizeof("foo1"),                                    0,  0,                                         0, VERR_MORE_DATA },
    73     { "=bar\0",                         sizeof("=bar"),                                    0,  0,                                         0, VERR_MORE_DATA },
    74     /* Last sequence is incomplete -- new offset should point to it. */
    75     { "hug=sub\0incomplete",            sizeof("hug=sub\0incomplete"),                     0,  sizeof("hug=sub"),                         1, VERR_MORE_DATA },
    76     { "boo=hoo\0baz=boo\0qwer",         sizeof("boo=hoo\0baz=boo\0qwer"),                  0,  sizeof("boo=hoo\0baz=boo"),                2, VERR_MORE_DATA },
    77     /* Parsing good stuff. */
    78     { "novalue=",                       sizeof("novalue="),                                0,  sizeof("novalue="),                        1, VINF_SUCCESS },
    79     { szUnterm2,                        8,                                                 0,  sizeof(szUnterm2),                         1, VINF_SUCCESS },
    80     { "foo2=",                          sizeof("foo2="),                                   0,  sizeof("foo2="),                           1, VINF_SUCCESS },
    81     { "har=hor",                        sizeof("har=hor"),                                 0,  sizeof("har=hor"),                         1, VINF_SUCCESS },
    82     { "foo=bar\0baz=boo",               sizeof("foo=bar\0baz=boo"),                        0,  sizeof("foo=bar\0baz=boo"),                2, VINF_SUCCESS },
    83     /* Parsing until a different block (two terminations, returning offset to next block). */
    84     { "off=rab\0a=b\0\0\0\0",           sizeof("off=rab\0a=b\0\0\0"),                      0,  13,                                        2, VERR_MORE_DATA },
    85     { "off=rab\0\0zab=oob",             sizeof("off=rab\0\0zab=oob"),                      0,  9,                                         1, VERR_MORE_DATA },
    86     { "\0\0\0\0off=rab\0zab=oob\0\0",   sizeof("\0\0\0\0off=rab\0zab=oob\0\0"),            0,  1,                                         0, VERR_MORE_DATA },
    87     { "o2=r2\0z3=o3\0\0f3=g3",          sizeof("o2=r2\0z3=o3\0\0f3=g3"),                   0,  13,                                        2, VERR_MORE_DATA }
     75    { "",                               1,                                                 0,  1,                                         0, VINF_SUCCESS },
     76    { "\0",                             1,                                                 0,  1,                                         0, VINF_SUCCESS },
     77    /* Unterminated values (missing "\0"). */
     78    { "test1",                          sizeof("test1"),                                   0,  0,                                         0, VERR_MORE_DATA },
     79    { "test2=",                         sizeof("test2="),                                  0,  0,                                         0, VERR_MORE_DATA },
     80    { "test3=test3",                    sizeof("test3=test3"),                             0,  0,                                         0, VERR_MORE_DATA },
     81    { "test4=test4\0t41",               sizeof("test4=test4\0t41"),                        0,  sizeof("test4=test4\0") - 1,               1, VERR_MORE_DATA },
     82    { "test5=test5\0t51=t51",           sizeof("test5=test5\0t51=t51"),                    0,  sizeof("test5=test5\0") - 1,               1, VERR_MORE_DATA },
     83    /* Next block unterminated. */
     84    { "t51=t51\0t52=t52\0\0t53=t53",    sizeof("t51=t51\0t52=t52\0\0t53=t53"),             0,  sizeof("t51=t51\0t52=t52\0") - 1,          2, VINF_SUCCESS },
     85    { "test6=test6\0\0t61=t61",         sizeof("test6=test6\0\0t61=t61"),                  0,  sizeof("test6=test6\0") - 1,               1, VINF_SUCCESS },
     86    /* Good stuff. */
     87    { "test61=\0test611=test611\0",     sizeof("test61=\0test611=test611\0"),              0,  sizeof("test61=\0test611=test611\0") - 1,  2, VINF_SUCCESS },
     88    { "test7=test7\0\0",                sizeof("test7=test7\0\0"),                         0,  sizeof("test7=test7\0") - 1,               1, VINF_SUCCESS },
     89    { "test8=test8\0t81=t81\0\0",       sizeof("test8=test8\0t81=t81\0\0"),                0,  sizeof("test8=test8\0t81=t81\0") - 1,      2, VINF_SUCCESS },
     90    /* Good stuff, but with a second block -- should be *not* taken into account since
     91     * we're only interested in parsing/handling the first object. */
     92    { "t9=t9\0t91=t91\0\0t92=t92\0\0",  sizeof("t9=t9\0t91=t91\0\0t92=t92\0\0"),           0,  sizeof("t9=t9\0t91=t91\0") - 1,            2, VINF_SUCCESS }
    8893};
    8994
     
    98103} aTests2[] =
    99104{
    100     { "\0\0\0\0",                                      sizeof("\0\0\0\0"),                                0, VINF_SUCCESS },
    101     { "off=rab\0\0zab=oob",                            sizeof("off=rab\0\0zab=oob"),                      2, VINF_SUCCESS },
    102     { "\0\0\0soo=foo\0goo=loo\0\0zab=oob",             sizeof("\0\0\0soo=foo\0goo=loo\0\0zab=oob"),       2, VINF_SUCCESS },
    103     { "qoo=uoo\0\0\0\0asdf=\0\0",                      sizeof("qoo=uoo\0\0\0\0asdf=\0\0"),                2, VINF_SUCCESS },
    104     { "foo=bar\0\0\0\0\0\0",                           sizeof("foo=bar\0\0\0\0\0\0"),                     1, VINF_SUCCESS },
    105     { "qwer=cvbnr\0\0\0gui=uig\0\0\0",                 sizeof("qwer=cvbnr\0\0\0gui=uig\0\0\0"),           2, VINF_SUCCESS }
     105    /* No blocks. */
     106    { "\0\0\0\0",                                      sizeof("\0\0\0\0"),                                0, VERR_NO_DATA },
     107    /* Good stuff. */
     108    { "\0b1=b1\0\0",                                   sizeof("\0b1=b1\0\0"),                             1, VERR_NO_DATA },
     109    { "b1=b1\0\0",                                     sizeof("b1=b1\0\0"),                               1, VERR_NO_DATA },
     110    { "b1=b1\0b2=b2\0\0",                              sizeof("b1=b1\0b2=b2\0\0"),                        1, VERR_NO_DATA },
     111    { "b1=b1\0b2=b2\0\0\0",                            sizeof("b1=b1\0b2=b2\0\0\0"),                      1, VERR_NO_DATA }
    106112};
    107113
     
    136142    for (iTest; iTest < RT_ELEMENTS(aTests); iTest++)
    137143    {
    138         uint32_t uOffset = aTests[iTest].uOffsetStart;
    139 
    140144        RTTestIPrintf(RTTESTLVL_DEBUG, "=> Test #%u\n", iTest);
    141145
     
    144148        if (RT_SUCCESS(iResult))
    145149        {
    146             GuestProcessStreamBlock block;
    147             iResult = stream.ParseBlock(block);
     150            GuestProcessStreamBlock curBlock;
     151            iResult = stream.ParseBlock(curBlock);
    148152            if (iResult != aTests[iTest].iResult)
    149153            {
     
    151155                             iResult, aTests[iTest].iResult);
    152156            }
    153             else if (block.GetCount() != aTests[iTest].uMapElements)
    154             {
    155                 RTTestFailed(hTest, "\tMap has %u elements, expected %u",
    156                              block.GetCount(), aTests[iTest].uMapElements);
    157             }
    158157            else if (stream.GetOffset() != aTests[iTest].uOffsetAfter)
    159158            {
     
    163162            else if (iResult == VERR_MORE_DATA)
    164163            {
    165                 RTTestIPrintf(RTTESTLVL_DEBUG, "\tMore data (Offset: %u)\n", uOffset);
    166 
    167                 /* There is remaining data left in the buffer (which needs to be merged
    168                  * with a following buffer) -- print it. */
    169                 size_t uToWrite = aTests[iTest].cbData - uOffset;
    170                 if (uToWrite)
     164                RTTestIPrintf(RTTESTLVL_DEBUG, "\tMore data (Offset: %u)\n", stream.GetOffset());
     165            }
     166
     167            if (  (   RT_SUCCESS(iResult)
     168                   || iResult == VERR_MORE_DATA))
     169            {
     170                if (curBlock.GetCount() != aTests[iTest].uMapElements)
    171171                {
    172                     const char *pszRemaining = aTests[iTest].pbData;
    173                     RTTestIPrintf(RTTESTLVL_DEBUG, "\tRemaining (%u):\n", uToWrite);
    174                     RTStrmWriteEx(g_pStdOut, &aTests[iTest].pbData[uOffset], uToWrite - 1, NULL);
    175                     RTTestIPrintf(RTTESTLVL_DEBUG, "\n");
     172                    RTTestFailed(hTest, "\tMap has %u elements, expected %u",
     173                                 curBlock.GetCount(), aTests[iTest].uMapElements);
    176174                }
     175            }
     176
     177            /* There is remaining data left in the buffer (which needs to be merged
     178             * with a following buffer) -- print it. */
     179            uint32_t uOffset = stream.GetOffset();
     180            size_t uToWrite = aTests[iTest].cbData - uOffset;
     181            if (uToWrite)
     182            {
     183                const char *pszRemaining = aTests[iTest].pbData;
     184                RTTestIPrintf(RTTESTLVL_DEBUG, "\tRemaining (%u):\n", uToWrite);
     185                RTStrmWriteEx(g_pStdOut, &aTests[iTest].pbData[uOffset], uToWrite - 1, NULL);
    177186            }
    178187        }
     
    181190    RTTestIPrintf(RTTESTLVL_INFO, "Doing block tests ...\n");
    182191
    183     for (unsigned iTest = 0; iTest < RT_ELEMENTS(aTests2); iTest++)
     192    iTest = 0;
     193    for (iTest; iTest < RT_ELEMENTS(aTests2); iTest++)
    184194    {
    185195        RTTestIPrintf(RTTESTLVL_DEBUG, "=> Block test #%u\n", iTest);
     
    190200        {
    191201            uint32_t uNumBlocks = 0;
    192 
     202            uint8_t uSafeCouunter = 0;
    193203            do
    194204            {
    195                 GuestProcessStreamBlock block;
    196                 iResult = stream.ParseBlock(block);
     205                GuestProcessStreamBlock curBlock;
     206                iResult = stream.ParseBlock(curBlock);
    197207                RTTestIPrintf(RTTESTLVL_DEBUG, "\tReturned with %Rrc\n", iResult);
    198                 if (   iResult == VINF_SUCCESS
    199                         || iResult == VERR_MORE_DATA)
     208                if (RT_SUCCESS(iResult))
    200209                {
    201210                    /* Only count block which have at least one pair. */
    202                     if (block.GetCount())
     211                    if (curBlock.GetCount())
    203212                        uNumBlocks++;
    204213                }
    205                 if (uNumBlocks > 32)
    206                     break; /* Give up if unreasonable big. */
    207                 block.Clear();
    208             } while (iResult == VERR_MORE_DATA);
     214                if (uSafeCouunter++ > 32)
     215                    break;
     216            } while (RT_SUCCESS(iResult));
    209217
    210218            if (iResult != aTests2[iTest].iResult)
Note: See TracChangeset for help on using the changeset viewer.

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