VirtualBox

Changeset 42673 in vbox for trunk


Ignore:
Timestamp:
Aug 8, 2012 8:07:09 AM (12 years ago)
Author:
vboxsync
Message:

Guest Control 2.0: Update.

Location:
trunk/src/VBox/Main
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r42657 r42673  
    93299329  <enum
    93309330    name="DirectoryOpenFlag"
    9331     uuid="fc8f6203-0072-4f34-bd08-0b35e50bf071"
     9331    uuid="5138837a-8fd2-4194-a1b0-08f7bc3949d0"
    93329332    >
    93339333    <desc>
     
    93369336    <const name="None"                    value="0">
    93379337      <desc>No flag set.</desc>
     9338    </const>
     9339    <const name="NoSymlinks"              value="1">
     9340      <desc>Don't allow symbolic links as part of the path.</desc>
    93389341    </const>
    93399342  </enum>
     
    93819384  <interface
    93829385    name="IGuestSession" extends="$unknown"
    9383     uuid="9233c0b5-8f0d-48b2-9b90-b730880f1e35"
     9386    uuid="45aca317-55d7-4b6c-bbec-d053289118b9"
    93849387    wsmap="managed"
    93859388    >
     
    95829585        <desc>TODO</desc>
    95839586      </param>
    9584       <param name="flags" type="wstring" dir="in">
     9587      <param name="flags" type="DirectoryOpenFlag" dir="in" safearray="yes">
    95859588        <desc>TODO</desc>
    95869589      </param>
     
    1023310236  <interface
    1023410237    name="IDirectory" extends="$unknown"
    10235     uuid="e55ab5e5-4feb-452b-86ed-59cff4c581a3"
     10238    uuid="1b70dd03-26d7-483a-8877-89bbb0f87b70"
    1023610239    wsmap="managed"
    1023710240    >
     
    1024910252    </attribute>
    1025010253   
    10251     <method name="read">
     10254    <attribute name="filter" type="wstring" readonly="yes">
     10255      <desc>
     10256        The open filter.
     10257        <note>
     10258          TODO
     10259        </note>
     10260      </desc>
     10261    </attribute>
     10262   
     10263    <method name="close">
    1025210264      <desc>
    1025310265        TODO
     
    1025510267        <result name="VBOX_E_NOT_SUPPORTED">
    1025610268          TODO
     10269        </result>
     10270      </desc>
     10271    </method>
     10272   
     10273    <method name="read">
     10274      <desc>
     10275        TODO
     10276
     10277        <result name="VBOX_E_OBJECT_NOT_FOUND">
     10278          End of directory listing reached.
    1025710279        </result>
    1025810280      </desc>
     
    1047210494  <interface
    1047310495    name="IFsObjInfo" extends="$unknown"
    10474     uuid="4925335b-9aa6-4870-bda3-8edb09fb602c"
     10496    uuid="4047ba30-7006-4966-ae86-94164e5e20eb"
    1047510497    wsmap="managed"
    1047610498    >
     
    1051910541      </desc>
    1052010542    </attribute>
    10521     <attribute name="fileAtttributes" type="wstring" readonly="yes">
     10543    <attribute name="fileAttributes" type="wstring" readonly="yes">
    1052210544      <desc>
    1052310545        TODO
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r42643 r42673  
    275275{
    276276    /** Helper function to extract the data from
    277      *  a guest stream block. */
    278     int From(const GuestProcessStreamBlock &strmBlk);
     277     *  a certin VBoxService tool's guest stream block. */
     278    int FromLs(const GuestProcessStreamBlock &strmBlk);
     279    int FromStat(const GuestProcessStreamBlock &strmBlk);
    279280
    280281    int64_t              mAccessTime;
     
    365366public:
    366367
    367     void Clear();
     368    void Clear(void);
    368369
    369370#ifdef DEBUG
    370     void Dump();
     371    void DumpToLog(void) const;
    371372#endif
    372373
     
    382383
    383384    uint32_t GetUInt32(const char *pszKey) const;
     385
     386    bool IsEmpty(void) { return m_mapPairs.empty(); }
    384387
    385388    int SetValue(const char *pszKey, const char *pszValue);
  • trunk/src/VBox/Main/include/GuestDirectoryImpl.h

    r42525 r42673  
    2121
    2222#include "VirtualBoxBase.h"
     23#include "GuestCtrlImplPrivate.h"
    2324
     25class GuestProcess;
    2426class GuestSession;
    2527
     
    4345    DECLARE_EMPTY_CTOR_DTOR(GuestDirectory)
    4446
    45     int     init(GuestSession *aSession, const Utf8Str &strPath);
     47    int     init(GuestSession *aSession, const Utf8Str &strPath, const Utf8Str &strFilter = "", uint32_t uFlags = 0);
    4648    void    uninit(void);
    4749    HRESULT FinalConstruct(void);
     
    5254     * @{ */
    5355    STDMETHOD(COMGETTER(DirectoryName))(BSTR *aName);
    54 
     56    STDMETHOD(COMGETTER(Filter))(BSTR *aFilter);
     57    STDMETHOD(Close)(void);
    5558    STDMETHOD(Read)(IFsObjInfo **aInfo);
    5659    /** @}  */
     
    6366private:
    6467
     68    /** @name Private internal methods.
     69     * @{ */
     70    int parseData(GuestProcessStreamBlock &streamBlock);
     71    /** @}  */
     72
    6573    struct Data
    6674    {
    67         GuestSession           *mParent;
    68         Utf8Str                 mName;
    69         ComPtr<IGuestFsObjInfo> mFsObjInfo;
     75        GuestSession              *mParent;
     76        Utf8Str                    mName;
     77        Utf8Str                    mFilter;
     78        uint32_t                   mFlags;
     79        /** The stdout stream object which contains all
     80         *  read out data for parsing. Must be persisent
     81         *  between several read() calls. */
     82        GuestProcessStream         mStream;
     83        /** The guest process which is responsible for
     84         *  getting the stdout stream. */
     85        ComObjPtr<GuestProcess>    mProcess;
    7086    } mData;
    7187};
  • trunk/src/VBox/Main/include/GuestFsObjInfoImpl.h

    r42530 r42673  
    4242    DECLARE_EMPTY_CTOR_DTOR(GuestFsObjInfo)
    4343
    44     HRESULT init(void);
     44    int     init(const GuestFsObjData &objData);
    4545    void    uninit(void);
    4646    HRESULT FinalConstruct(void);
     
    5555    STDMETHOD(COMGETTER(ChangeTime))(LONG64 *aChangeTime);
    5656    STDMETHOD(COMGETTER(DeviceNumber))(ULONG *aDeviceNumber);
    57     STDMETHOD(COMGETTER(FileAttrs))(BSTR *aFileAttrs);
    58     STDMETHOD(COMGETTER(GenerationID))(ULONG *aGenerationID);
     57    STDMETHOD(COMGETTER(FileAttributes))(BSTR *aFileAttrs);
     58    STDMETHOD(COMGETTER(GenerationId))(ULONG *aGenerationId);
    5959    STDMETHOD(COMGETTER(GID))(ULONG *aGID);
    6060    STDMETHOD(COMGETTER(GroupName))(BSTR *aGroupName);
     
    6262    STDMETHOD(COMGETTER(ModificationTime))(LONG64 *aModificationTime);
    6363    STDMETHOD(COMGETTER(Name))(BSTR *aName);
    64     STDMETHOD(COMGETTER(NodeID))(LONG64 *aNodeID);
    65     STDMETHOD(COMGETTER(NodeIDDevice))(ULONG *aNodeIDDevice);
    66     STDMETHOD(COMGETTER(ObjectSize))(ULONG *aObjectSize);
     64    STDMETHOD(COMGETTER(NodeId))(LONG64 *aNodeId);
     65    STDMETHOD(COMGETTER(NodeIdDevice))(ULONG *aNodeIdDevice);
     66    STDMETHOD(COMGETTER(ObjectSize))(LONG64 *aObjectSize);
    6767    STDMETHOD(COMGETTER(Type))(FsObjType_T *aType);
    6868    STDMETHOD(COMGETTER(UID))(ULONG *aUID);
  • trunk/src/VBox/Main/include/GuestProcessImpl.h

    r42634 r42673  
    7474    int callbackDispatcher(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData);
    7575    inline bool callbackExists(uint32_t uContextID);
     76    inline int checkPID(uint32_t uPID);
    7677    void close(void);
    7778    bool isReady(void);
     
    8384    int terminateProcess(void);
    8485    int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestProcessWaitResult &guestResult);
     86    int waitForStart(uint32_t uTimeoutMS);
    8587    int writeData(uint32_t uHandle, uint32_t uFlags, void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten);
    8688    /** @}  */
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r42657 r42673  
    157157    STDMETHOD(DirectoryCreateTemp)(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aName, IGuestDirectory **aDirectory);
    158158    STDMETHOD(DirectoryExists)(IN_BSTR aPath, BOOL *aExists);
    159     STDMETHOD(DirectoryOpen)(IN_BSTR aPath, IN_BSTR aFilter, IN_BSTR aFlags, IGuestDirectory **aDirectory);
     159    STDMETHOD(DirectoryOpen)(IN_BSTR aPath, IN_BSTR aFilter, ComSafeArrayIn(DirectoryOpenFlag_T, aFlags), IGuestDirectory **aDirectory);
    160160    STDMETHOD(DirectoryQueryInfo)(IN_BSTR aPath, IGuestFsObjInfo **aInfo);
    161161    STDMETHOD(DirectoryRemove)(IN_BSTR aPath);
     
    205205    int                     directoryClose(ComObjPtr<GuestDirectory> pDirectory);
    206206    int                     directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory);
     207    int                     directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory);
    207208    int                     dispatchToProcess(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData);
    208209    int                     fileClose(ComObjPtr<GuestFile> pFile);
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r42634 r42673  
    736736    int rc = VINF_SUCCESS;
    737737    if (fDispatch)
     738    {
    738739        rc = pGuest->dispatchToSession(pHeader->u32ContextID, u32Function, pvParms, cbParms);
    739 
    740 #ifdef VBOX_WITH_GUEST_CONTROL_LEGACY
    741     if (RT_SUCCESS(rc))
    742         return rc;
     740        if (RT_SUCCESS(rc))
     741            return rc;
     742    }
     743
     744#ifdef DEBUG
     745    /* @todo Don't use legacy stuff in debug mode. Remove for final! */
     746    return rc;
     747#endif
    743748
    744749    /* Legacy handling. */
     
    794799            break;
    795800    }
    796 #endif /* VBOX_WITH_GUEST_CONTROL_LEGACY */
    797801
    798802    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Main/src-client/GuestCtrlImplDir.cpp

    r41222 r42673  
    593593                {
    594594#ifdef DEBUG
    595                     streamBlock.Dump();
     595                    streamBlock.DumpToLog();
    596596#endif
    597597                    hr = VBOX_E_FILE_ERROR;
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r42634 r42673  
    581581}
    582582
    583 int GuestFsObjData::From(const GuestProcessStreamBlock &strmBlk)
    584 {
     583int GuestFsObjData::FromLs(const GuestProcessStreamBlock &strmBlk)
     584{
     585    LogFlowFuncEnter(("\n"));
     586
    585587    int rc = VINF_SUCCESS;
    586588
    587589    try
    588590    {
     591#ifdef DEBUG
     592        strmBlk.DumpToLog();
     593#endif
     594        /* Object name. */
     595        mName = strmBlk.GetString("name");
     596        if (mName.isEmpty()) throw VERR_NOT_FOUND;
     597        /* Type. */
    589598        Utf8Str strType(strmBlk.GetString("ftype"));
    590599        if (strType.equalsIgnoreCase("-"))
     
    595604        else
    596605            mType = FsObjType_Undefined;
    597 
     606        /* Object size. */
    598607        rc = strmBlk.GetInt64Ex("st_size", &mObjectSize);
    599608        if (RT_FAILURE(rc)) throw rc;
    600 
    601         /** @todo Add complete GuestFsObjData info! */
     609        /** @todo Add complete ls info! */
    602610    }
    603611    catch (int rc2)
     
    606614    }
    607615
     616    LogFlowFuncLeaveRC(rc);
     617    return rc;
     618}
     619
     620int GuestFsObjData::FromStat(const GuestProcessStreamBlock &strmBlk)
     621{
     622    LogFlowFuncEnter(("\n"));
     623
     624    int rc = VINF_SUCCESS;
     625
     626    try
     627    {
     628#ifdef DEBUG
     629        strmBlk.DumpToLog();
     630#endif
     631        /* Node ID. */
     632        rc = strmBlk.GetInt64Ex("node_id", &mNodeID);
     633        if (RT_FAILURE(rc)) throw rc;
     634        /* Object name. */
     635        mName = strmBlk.GetString("name");
     636        if (mName.isEmpty()) throw VERR_NOT_FOUND;
     637        /* Type. */
     638        Utf8Str strType(strmBlk.GetString("ftype"));
     639        if (strType.equalsIgnoreCase("-"))
     640            mType = FsObjType_File;
     641        else if (strType.equalsIgnoreCase("d"))
     642            mType = FsObjType_Directory;
     643        /** @todo Add more types! */
     644        else
     645            mType = FsObjType_Undefined;
     646        /* Object size. */
     647        rc = strmBlk.GetInt64Ex("st_size", &mObjectSize);
     648        if (RT_FAILURE(rc)) throw rc;
     649        /** @todo Add complete stat info! */
     650    }
     651    catch (int rc2)
     652    {
     653        rc = rc2;
     654    }
     655
     656    LogFlowFuncLeaveRC(rc);
    608657    return rc;
    609658}
     
    650699
    651700#ifdef DEBUG
    652 void GuestProcessStreamBlock::Dump(void)
     701void GuestProcessStreamBlock::DumpToLog(void) const
    653702{
    654703    LogFlowFunc(("Dumping contents of stream block=0x%p (%ld items):\n",
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r42525 r42673  
    2222*******************************************************************************/
    2323#include "GuestDirectoryImpl.h"
     24#include "GuestSessionImpl.h"
    2425#include "GuestCtrlImplPrivate.h"
    2526
     
    5253/////////////////////////////////////////////////////////////////////////////
    5354
    54 int GuestDirectory::init(GuestSession *aSession, const Utf8Str &strPath)
    55 {
     55int GuestDirectory::init(GuestSession *aSession,
     56                         const Utf8Str &strPath, const Utf8Str &strFilter /*= ""*/, uint32_t uFlags /*= 0*/)
     57{
     58    LogFlowThisFunc(("strPath=%s, strFilter=%s, uFlags=%x\n",
     59                     strPath.c_str(), strFilter.c_str(), uFlags));
     60
    5661    /* Enclose the state transition NotReady->InInit->Ready. */
    5762    AutoInitSpan autoInitSpan(this);
     
    5964
    6065    mData.mParent = aSession;
    61     mData.mName = strPath;
    62 
    63     /* Confirm a successful initialization when it's the case. */
    64     autoInitSpan.setSucceeded();
    65 
    66     return VINF_SUCCESS;
     66    mData.mName   = strPath;
     67    mData.mFilter = strFilter;
     68    mData.mFlags  = uFlags;
     69
     70    /* Start the directory process on the guest. */
     71    GuestProcessStartupInfo procInfo;
     72    procInfo.mName      = Utf8StrFmt(tr("Reading directory \"%s\"", strPath.c_str()));
     73    procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_LS);
     74    procInfo.mTimeoutMS = 0; /* No timeout. */
     75    procInfo.mFlags     = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
     76
     77    procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     78    /* We want the long output format which contains all the object details. */
     79    procInfo.mArguments.push_back(Utf8Str("-l"));
     80#if 0 /* Flags are not supported yet. */
     81    if (uFlags & DirectoryOpenFlag_NoSymlinks)
     82        procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
     83#endif
     84    /** @todo Recursion support? */
     85    procInfo.mArguments.push_back(strPath); /* The directory we want to open. */
     86
     87    /*
     88     * Start the process asynchronously and keep it around so that we can use
     89     * it later in subsequent read() calls.
     90     */
     91    int rc = mData.mParent->processCreateExInteral(procInfo, mData.mProcess);
     92    if (RT_SUCCESS(rc))
     93        rc = mData.mProcess->startProcessAsync();
     94
     95    LogFlowThisFunc(("rc=%Rrc\n", rc));
     96
     97    if (RT_SUCCESS(rc))
     98    {
     99        /* Confirm a successful initialization when it's the case. */
     100        autoInitSpan.setSucceeded();
     101        return rc;
     102    }
     103
     104    autoInitSpan.setFailed();
     105    return rc;
    67106}
    68107
     
    79118    if (autoUninitSpan.uninitDone())
    80119        return;
     120
     121    if (!mData.mProcess.isNull())
     122        mData.mProcess->uninit();
    81123}
    82124
     
    100142}
    101143
     144STDMETHODIMP GuestDirectory::COMGETTER(Filter)(BSTR *aFilter)
     145{
     146    LogFlowThisFuncEnter();
     147
     148    CheckComArgOutPointerValid(aFilter);
     149
     150    AutoCaller autoCaller(this);
     151    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     152
     153    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     154
     155    mData.mFilter.cloneTo(aFilter);
     156
     157    return S_OK;
     158}
     159
     160// private methods
     161/////////////////////////////////////////////////////////////////////////////
     162
     163int GuestDirectory::parseData(GuestProcessStreamBlock &streamBlock)
     164{
     165    LogFlowThisFunc(("cbStream=%RU32\n", mData.mStream.GetSize()));
     166
     167    int rc;
     168    do
     169    {
     170        /* Try parsing the data to see if the current block is complete. */
     171        rc = mData.mStream.ParseBlock(streamBlock);
     172        if (streamBlock.GetCount())
     173            break;
     174
     175    } while (RT_SUCCESS(rc));
     176
     177    LogFlowFuncLeaveRC(rc);
     178    return rc;
     179}
     180
     181
    102182// implementation of public methods
    103183/////////////////////////////////////////////////////////////////////////////
    104184
    105 STDMETHODIMP GuestDirectory::Read(IFsObjInfo **aInfo)
     185STDMETHODIMP GuestDirectory::Close(void)
    106186{
    107187#ifndef VBOX_WITH_GUEST_CONTROL
    108188    ReturnComNotImplemented();
    109189#else
     190    LogFlowThisFuncEnter();
     191
     192    uninit();
     193
     194    return S_OK;
     195#endif /* VBOX_WITH_GUEST_CONTROL */
     196}
     197
     198STDMETHODIMP GuestDirectory::Read(IFsObjInfo **aInfo)
     199{
     200#ifndef VBOX_WITH_GUEST_CONTROL
     201    ReturnComNotImplemented();
     202#else
     203    LogFlowThisFuncEnter();
     204
    110205    AutoCaller autoCaller(this);
    111206    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    112207
    113     ReturnComNotImplemented();
     208    ComObjPtr<GuestProcess> pProcess = mData.mProcess;
     209    Assert(!pProcess.isNull());
     210
     211    HRESULT hr = S_OK;
     212
     213    int rc;
     214    GuestProcessStreamBlock streamBlock;
     215
     216    /** @todo Make use of exceptions! */
     217
     218    try
     219    {
     220        GuestFsObjData objData;
     221
     222        AutoWriteLock rlock(this COMMA_LOCKVAL_SRC_POS);
     223
     224        rc = parseData(streamBlock);
     225        if (   RT_FAILURE(rc)
     226            || streamBlock.IsEmpty()) /* More data needed. */
     227        {
     228            rlock.release();
     229
     230            rc = pProcess->waitForStart(30 * 1000 /* Timeout */);
     231            if (RT_FAILURE(rc))
     232                return setError(VBOX_E_IPRT_ERROR,
     233                                tr("Could not start reading directory \"%s\": %Rrc"),
     234                                mData.mName.c_str(), rc);
     235            BYTE byBuf[_64K];
     236            size_t cbRead = 0;
     237
     238            /** @todo Merge with GuestSession::queryFileInfoInternal. */
     239            for (;;)
     240            {
     241                GuestProcessWaitResult waitRes;
     242                rc = pProcess->waitFor(  ProcessWaitForFlag_Terminate
     243                                       | ProcessWaitForFlag_StdOut,
     244                                       30 * 1000 /* Timeout */, waitRes);
     245                if (   RT_FAILURE(rc)
     246                    || waitRes.mResult == ProcessWaitResult_Terminate
     247                    || waitRes.mResult == ProcessWaitResult_Error
     248                    || waitRes.mResult == ProcessWaitResult_Timeout)
     249                {
     250                    break;
     251                }
     252
     253                rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
     254                                        30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
     255                                        &cbRead);
     256                if (RT_FAILURE(rc))
     257                    break;
     258
     259                if (cbRead)
     260                {
     261                    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     262
     263                    rc = mData.mStream.AddData(byBuf, cbRead);
     264                    if (RT_FAILURE(rc))
     265                        break;
     266
     267                    LogFlowThisFunc(("rc=%Rrc, cbRead=%RU64, cbStreamOut=%RU32\n",
     268                                     rc, cbRead, mData.mStream.GetSize()));
     269
     270                    rc = parseData(streamBlock);
     271                    if (RT_SUCCESS(rc))
     272                    {
     273                        /* Parsing the current stream block succeeded so
     274                         * we don't need more at the moment. */
     275                        break;
     276                    }
     277                }
     278            }
     279
     280            LogFlowThisFunc(("Reading done with rc=%Rrc, cbRead=%RU64, cbStream=%RU32\n",
     281                             rc, cbRead, mData.mStream.GetSize()));
     282
     283            if (RT_SUCCESS(rc))
     284            {
     285                rc = parseData(streamBlock);
     286                if (rc == VERR_NO_DATA) /* Since this is the last parsing call, this is ok. */
     287                    rc = VINF_SUCCESS;
     288            }
     289
     290            /*
     291             * Note: The guest process can still be around to serve the next
     292             *       upcoming stream block next time.
     293             */
     294            if (RT_SUCCESS(rc))
     295            {
     296                /** @todo Move into common function. */
     297                ProcessStatus_T procStatus = ProcessStatus_Undefined;
     298                LONG exitCode = 0;
     299
     300                HRESULT hr = pProcess->COMGETTER(Status(&procStatus));
     301                ComAssertComRC(hr);
     302                hr = pProcess->COMGETTER(ExitCode(&exitCode));
     303                ComAssertComRC(hr);
     304
     305                if (   (   procStatus != ProcessStatus_Started
     306                        && procStatus != ProcessStatus_Paused
     307                        && procStatus != ProcessStatus_Terminating
     308                       )
     309                    && exitCode != 0)
     310                {
     311                    return setError(VBOX_E_IPRT_ERROR,
     312                                    tr("Reading directory \"%s\" failed: Unable to read / access denied"),
     313                                    mData.mName.c_str(), exitCode); /**@todo Add stringify methods! */
     314                }
     315            }
     316        }
     317
     318        if (RT_SUCCESS(rc))
     319        {
     320            if (streamBlock.GetCount()) /* Did we get content? */
     321            {
     322                rc = objData.FromLs(streamBlock);
     323                if (RT_FAILURE(rc))
     324                    return setError(VBOX_E_IPRT_ERROR,
     325                                    tr("Reading directory \"%s\" failed: Path not found"),
     326                                    mData.mName.c_str());
     327
     328                /* Create the object. */
     329                ComObjPtr<GuestFsObjInfo> pFsObjInfo;
     330                HRESULT hr = pFsObjInfo.createObject();
     331                if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
     332
     333                rc = pFsObjInfo->init(objData);
     334                if (RT_FAILURE(rc)) throw rc;
     335
     336                /* Return info object to the caller. */
     337                hr = pFsObjInfo.queryInterfaceTo(aInfo);
     338                if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
     339            }
     340            else
     341            {
     342                /* Nothing to read anymore. Tell the caller. */
     343                hr = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No more entries for directory \"%s\""),
     344                              mData.mName.c_str());
     345            }
     346        }
     347    }
     348    catch (int rc2)
     349    {
     350        rc = rc2;
     351    }
     352
     353    if (RT_FAILURE(rc)) /** @todo Add more errors here. */
     354        hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"),
     355                      mData.mName.c_str(), rc);
     356
     357    LogFlowFuncLeaveRC(rc);
     358    return hr;
    114359#endif /* VBOX_WITH_GUEST_CONTROL */
    115360}
  • trunk/src/VBox/Main/src-client/GuestFsObjInfoImpl.cpp

    r42478 r42673  
    5252/////////////////////////////////////////////////////////////////////////////
    5353
    54 HRESULT GuestFsObjInfo::init(void)
    55 {
    56     return S_OK;
     54int GuestFsObjInfo::init(const GuestFsObjData &objData)
     55{
     56    LogFlowThisFuncEnter();
     57
     58    /* Enclose the state transition NotReady->InInit->Ready. */
     59    AutoInitSpan autoInitSpan(this);
     60    AssertReturn(autoInitSpan.isOk(), E_FAIL);
     61
     62    mData = objData;
     63
     64    /* Confirm a successful initialization when it's the case. */
     65    autoInitSpan.setSucceeded();
     66
     67    return VINF_SUCCESS;
    5768}
    5869
     
    8293    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    8394
    84     ReturnComNotImplemented();
     95    CheckComArgOutPointerValid(aAccessTime);
     96
     97    *aAccessTime = mData.mAccessTime;
     98
     99    return S_OK;
    85100#endif /* VBOX_WITH_GUEST_CONTROL */
    86101}
     
    94109    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    95110
    96     ReturnComNotImplemented();
     111    CheckComArgOutPointerValid(aAllocatedSize);
     112
     113    *aAllocatedSize = mData.mAllocatedSize;
     114
     115    return S_OK;
    97116#endif /* VBOX_WITH_GUEST_CONTROL */
    98117}
     
    106125    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    107126
    108     ReturnComNotImplemented();
     127    CheckComArgOutPointerValid(aBirthTime);
     128
     129    *aBirthTime = mData.mBirthTime;
     130
     131    return S_OK;
    109132#endif /* VBOX_WITH_GUEST_CONTROL */
    110133}
     
    118141    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    119142
    120     ReturnComNotImplemented();
     143    CheckComArgOutPointerValid(aChangeTime);
     144
     145    *aChangeTime = mData.mChangeTime;
     146
     147    return S_OK;
    121148#endif /* VBOX_WITH_GUEST_CONTROL */
    122149}
     
    130157    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    131158
    132     ReturnComNotImplemented();
    133 #endif /* VBOX_WITH_GUEST_CONTROL */
    134 }
    135 
    136 STDMETHODIMP GuestFsObjInfo::COMGETTER(FileAttrs)(BSTR *aFileAttrs)
    137 {
    138 #ifndef VBOX_WITH_GUEST_CONTROL
    139     ReturnComNotImplemented();
    140 #else
    141     AutoCaller autoCaller(this);
    142     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    143 
    144     ReturnComNotImplemented();
    145 #endif /* VBOX_WITH_GUEST_CONTROL */
    146 }
    147 
    148 STDMETHODIMP GuestFsObjInfo::COMGETTER(GenerationID)(ULONG *aGenerationID)
    149 {
    150 #ifndef VBOX_WITH_GUEST_CONTROL
    151     ReturnComNotImplemented();
    152 #else
    153     AutoCaller autoCaller(this);
    154     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    155 
    156     ReturnComNotImplemented();
     159    CheckComArgOutPointerValid(aDeviceNumber);
     160
     161    *aDeviceNumber = mData.mDeviceNumber;
     162
     163    return S_OK;
     164#endif /* VBOX_WITH_GUEST_CONTROL */
     165}
     166
     167STDMETHODIMP GuestFsObjInfo::COMGETTER(FileAttributes)(BSTR *aAttributes)
     168{
     169#ifndef VBOX_WITH_GUEST_CONTROL
     170    ReturnComNotImplemented();
     171#else
     172    AutoCaller autoCaller(this);
     173    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     174
     175    CheckComArgOutPointerValid(aAttributes);
     176
     177    mData.mFileAttrs.cloneTo(aAttributes);
     178
     179    return S_OK;
     180#endif /* VBOX_WITH_GUEST_CONTROL */
     181}
     182
     183STDMETHODIMP GuestFsObjInfo::COMGETTER(GenerationId)(ULONG *aGenerationId)
     184{
     185#ifndef VBOX_WITH_GUEST_CONTROL
     186    ReturnComNotImplemented();
     187#else
     188    AutoCaller autoCaller(this);
     189    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     190
     191    CheckComArgOutPointerValid(aGenerationId);
     192
     193    *aGenerationId = mData.mGenerationID;
     194
     195    return S_OK;
    157196#endif /* VBOX_WITH_GUEST_CONTROL */
    158197}
     
    166205    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    167206
    168     ReturnComNotImplemented();
     207    CheckComArgOutPointerValid(aGID);
     208
     209    *aGID = mData.mGID;
     210
     211    return S_OK;
    169212#endif /* VBOX_WITH_GUEST_CONTROL */
    170213}
     
    178221    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    179222
    180     ReturnComNotImplemented();
     223    CheckComArgOutPointerValid(aGroupName);
     224
     225    mData.mGroupName.cloneTo(aGroupName);
     226
     227    return S_OK;
    181228#endif /* VBOX_WITH_GUEST_CONTROL */
    182229}
     
    190237    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    191238
    192     ReturnComNotImplemented();
     239    CheckComArgOutPointerValid(aHardLinks);
     240
     241    *aHardLinks = mData.mNumHardLinks;
     242
     243    return S_OK;
    193244#endif /* VBOX_WITH_GUEST_CONTROL */
    194245}
     
    202253    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    203254
    204     ReturnComNotImplemented();
     255    CheckComArgOutPointerValid(aModificationTime);
     256
     257    *aModificationTime = mData.mModificationTime;
     258
     259    return S_OK;
    205260#endif /* VBOX_WITH_GUEST_CONTROL */
    206261}
     
    214269    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    215270
    216     ReturnComNotImplemented();
    217 #endif /* VBOX_WITH_GUEST_CONTROL */
    218 }
    219 
    220 STDMETHODIMP GuestFsObjInfo::COMGETTER(NodeID)(LONG64 *aNodeID)
    221 {
    222 #ifndef VBOX_WITH_GUEST_CONTROL
    223     ReturnComNotImplemented();
    224 #else
    225     AutoCaller autoCaller(this);
    226     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    227 
    228     ReturnComNotImplemented();
    229 #endif /* VBOX_WITH_GUEST_CONTROL */
    230 }
    231 
    232 STDMETHODIMP GuestFsObjInfo::COMGETTER(NodeIDDevice)(ULONG *aNodeIDDevice)
    233 {
    234 #ifndef VBOX_WITH_GUEST_CONTROL
    235     ReturnComNotImplemented();
    236 #else
    237     AutoCaller autoCaller(this);
    238     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    239 
    240     ReturnComNotImplemented();
    241 #endif /* VBOX_WITH_GUEST_CONTROL */
    242 }
    243 
    244 STDMETHODIMP GuestFsObjInfo::COMGETTER(ObjectSize)(ULONG *aObjectSize)
    245 {
    246 #ifndef VBOX_WITH_GUEST_CONTROL
    247     ReturnComNotImplemented();
    248 #else
    249     AutoCaller autoCaller(this);
    250     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    251 
    252     ReturnComNotImplemented();
     271    CheckComArgOutPointerValid(aName);
     272
     273    mData.mName.cloneTo(aName);
     274
     275    return S_OK;
     276#endif /* VBOX_WITH_GUEST_CONTROL */
     277}
     278
     279STDMETHODIMP GuestFsObjInfo::COMGETTER(NodeId)(LONG64 *aNodeId)
     280{
     281#ifndef VBOX_WITH_GUEST_CONTROL
     282    ReturnComNotImplemented();
     283#else
     284    AutoCaller autoCaller(this);
     285    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     286
     287    CheckComArgOutPointerValid(aNodeId);
     288
     289    *aNodeId = mData.mNodeID;
     290
     291    return S_OK;
     292#endif /* VBOX_WITH_GUEST_CONTROL */
     293}
     294
     295STDMETHODIMP GuestFsObjInfo::COMGETTER(NodeIdDevice)(ULONG *aNodeIdDevice)
     296{
     297#ifndef VBOX_WITH_GUEST_CONTROL
     298    ReturnComNotImplemented();
     299#else
     300    AutoCaller autoCaller(this);
     301    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     302
     303    CheckComArgOutPointerValid(aNodeIdDevice);
     304
     305    *aNodeIdDevice = mData.mNodeIDDevice;
     306
     307    return S_OK;
     308#endif /* VBOX_WITH_GUEST_CONTROL */
     309}
     310
     311STDMETHODIMP GuestFsObjInfo::COMGETTER(ObjectSize)(LONG64 *aObjectSize)
     312{
     313#ifndef VBOX_WITH_GUEST_CONTROL
     314    ReturnComNotImplemented();
     315#else
     316    AutoCaller autoCaller(this);
     317    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     318
     319    CheckComArgOutPointerValid(aObjectSize);
     320
     321    *aObjectSize = mData.mObjectSize;
     322
     323    return S_OK;
    253324#endif /* VBOX_WITH_GUEST_CONTROL */
    254325}
     
    262333    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    263334
    264     ReturnComNotImplemented();
     335    CheckComArgOutPointerValid(aType);
     336
     337    *aType = mData.mType;
     338
     339    return S_OK;
    265340#endif /* VBOX_WITH_GUEST_CONTROL */
    266341}
     
    274349    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    275350
    276     ReturnComNotImplemented();
     351    CheckComArgOutPointerValid(aUID);
     352
     353    *aUID = mData.mUID;
     354
     355    return S_OK;
    277356#endif /* VBOX_WITH_GUEST_CONTROL */
    278357}
     
    286365    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    287366
    288     ReturnComNotImplemented();
     367    CheckComArgOutPointerValid(aUserFlags);
     368
     369    *aUserFlags = mData.mUserFlags;
     370
     371    return S_OK;
    289372#endif /* VBOX_WITH_GUEST_CONTROL */
    290373}
     
    298381    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    299382
    300     ReturnComNotImplemented();
     383    CheckComArgOutPointerValid(aUserName);
     384
     385    mData.mUserName.cloneTo(aUserName);
     386
     387    return S_OK;
    301388#endif /* VBOX_WITH_GUEST_CONTROL */
    302389}
     
    310397    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    311398
    312     ReturnComNotImplemented();
    313 #endif /* VBOX_WITH_GUEST_CONTROL */
    314 }
    315 
     399    CheckComArgOutPointerValid(aACL);
     400
     401    mData.mACL.cloneTo(aACL);
     402
     403    return S_OK;
     404#endif /* VBOX_WITH_GUEST_CONTROL */
     405}
     406
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r42634 r42673  
    498498}
    499499
     500/**
     501 * Checks if the current assigned PID matches another PID (from a callback).
     502 *
     503 * In protocol v1 we don't have the possibility to terminate/kill
     504 * processes so it can happen that a formerly start process A
     505 * (which has the context ID 0 (session=0, process=0, count=0) will
     506 * send a delayed message to the host if this process has already
     507 * been discarded there and the same context ID was reused by
     508 * a process B. Process B in turn then has a different guest PID.
     509 *
     510 * @return  IPRT status code.
     511 * @param   uPID                    PID to check.
     512 */
     513inline int GuestProcess::checkPID(uint32_t uPID)
     514{
     515    /* Was there a PID assigned yet? */
     516    if (mData.mPID)
     517    {
     518        /*
     519
     520         */
     521        if (mData.mParent->getProtocolVersion() < 2)
     522        {
     523            /* Simply ignore the stale requests. */
     524            return (mData.mPID == uPID)
     525                   ? VINF_SUCCESS : VERR_NOT_FOUND;
     526        }
     527        /* This should never happen! */
     528        AssertReleaseMsg(mData.mPID == uPID, ("Unterminated guest process (PID %RU32) sent data to a newly started process (PID %RU32)\n",
     529                                              uPID, mData.mPID));
     530    }
     531
     532    return VINF_SUCCESS;
     533}
     534
     535/* Do not hold any locks here because the lock validator will be unhappy
     536 * when being in uninit(). */
     537void GuestProcess::close(void)
     538{
     539    LogFlowThisFuncEnter();
     540
     541    uninit();
     542
     543    LogFlowThisFuncLeave();
     544}
     545
    500546inline bool GuestProcess::isAlive(void)
    501547{
     
    503549            || mData.mStatus == ProcessStatus_Paused
    504550            || mData.mStatus == ProcessStatus_Terminating);
    505 }
    506 
    507 /* Do not hold any locks here because the lock validator will be unhappy
    508  * when being in uninit(). */
    509 void GuestProcess::close(void)
    510 {
    511     LogFlowThisFuncEnter();
    512 
    513     uninit();
    514 
    515     LogFlowThisFuncLeave();
    516551}
    517552
     
    565600                     mData.mPID, pData->u32Status, pData->u32Flags, pData->cbProcessed, pCallback, pData));
    566601
    567     int rc = VINF_SUCCESS;
     602    int rc = checkPID(pData->u32PID);
     603    if (RT_FAILURE(rc))
     604        return rc;
    568605
    569606    /* First, signal callback in every case (if available). */
     
    607644                     pData->u32PID, pData->u32Status, pData->u32Flags, pCallback, pData));
    608645
    609     int rc = VINF_SUCCESS;
    610 
    611     /* Get data from the callback payload. */
    612     if (mData.mPID)
    613         Assert(mData.mPID == pData->u32PID);
     646    int rc = checkPID(pData->u32PID);
     647    if (RT_FAILURE(rc))
     648        return rc;
    614649
    615650    BOOL fSignal = FALSE;
     
    791826                     mData.mPID, pData->u32HandleId, pData->u32Flags, pData->pvData, pData->cbData, pCallback, pData));
    792827
    793     /* Copy data into callback (if any). */
    794     int rc = VINF_SUCCESS;
     828    int rc = checkPID(pData->u32PID);
     829    if (RT_FAILURE(rc))
     830        return rc;
    795831
    796832    /* First, signal callback in every case (if available). */
     
    12291265            case ProcessStatus_Down:
    12301266                waitRes.mResult = ProcessWaitResult_Terminate;
     1267                waitRes.mRC = mData.mRC;
    12311268                break;
    12321269
     
    12341271            case ProcessStatus_TimedOutAbnormally:
    12351272                waitRes.mResult = ProcessWaitResult_Timeout;
     1273                waitRes.mRC = mData.mRC;
    12361274                break;
    12371275
     
    12711309                break;
    12721310
     1311            case ProcessStatus_TimedOutKilled:
     1312            case ProcessStatus_TimedOutAbnormally:
     1313                waitRes.mResult = ProcessWaitResult_Timeout;
     1314                waitRes.mRC = mData.mRC;
     1315                break;
     1316
    12731317            case ProcessStatus_Undefined:
    12741318            case ProcessStatus_Starting:
     
    13101354
    13111355    mData.mWaitCount--;
     1356
     1357    LogFlowFuncLeaveRC(rc);
     1358    return rc;
     1359}
     1360
     1361int GuestProcess::waitForStart(uint32_t uTimeoutMS)
     1362{
     1363    LogFlowThisFunc(("uTimeoutMS=%RU32\n", uTimeoutMS));
     1364
     1365    int rc = VINF_SUCCESS;
     1366
     1367    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1368    if (mData.mStatus != ProcessStatus_Started)
     1369    {
     1370        alock.release();
     1371
     1372        GuestProcessWaitResult waitRes;
     1373        int rc = waitFor(ProcessWaitForFlag_Start, uTimeoutMS, waitRes);
     1374        if (   RT_FAILURE(rc)
     1375            || (    waitRes.mResult == ProcessWaitResult_Start
     1376                &&  waitRes.mResult == ProcessWaitResult_Any
     1377               )
     1378           )
     1379        {
     1380            if (RT_SUCCESS(rc))
     1381                rc = waitRes.mRC;
     1382        }
     1383    }
    13121384
    13131385    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r42657 r42673  
    10921092}
    10931093
     1094int GuestSession::directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter,
     1095                                        uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory)
     1096{
     1097    LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
     1098                     strPath.c_str(), strFilter.c_str(), uFlags));
     1099    int rc;
     1100
     1101    try
     1102    {
     1103        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1104
     1105        /* Create the directory object. */
     1106        HRESULT hr = pDirectory.createObject();
     1107        if (FAILED(hr)) throw VERR_COM_UNEXPECTED;
     1108
     1109        rc = pDirectory->init(this /* Parent */,
     1110                              strPath, strFilter, uFlags);
     1111        if (RT_FAILURE(rc)) throw rc;
     1112
     1113        /* Add the created directory to our vector. */
     1114        mData.mDirectories.push_back(pDirectory);
     1115
     1116        LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
     1117                     strPath.c_str(), mData.mId));
     1118    }
     1119    catch (int rc2)
     1120    {
     1121        rc = rc2;
     1122    }
     1123
     1124    LogFlowFuncLeaveRC(rc);
     1125    return rc;
     1126}
     1127
    10941128int GuestSession::dispatchToProcess(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData)
    10951129{
     
    11981232        size_t cbRead = 0;
    11991233
     1234        /** @todo Merge with GuestDirectory::read. */
    12001235        for (;;)
    12011236        {
     
    12341269        if (RT_SUCCESS(rc))
    12351270        {
    1236             rc = objData.From(streamBlock);
     1271            rc = objData.FromStat(streamBlock);
    12371272        }
    12381273        else
     
    18181853}
    18191854
    1820 STDMETHODIMP GuestSession::DirectoryOpen(IN_BSTR aPath, IN_BSTR aFilter, IN_BSTR aFlags, IGuestDirectory **aDirectory)
    1821 {
    1822 #ifndef VBOX_WITH_GUEST_CONTROL
    1823     ReturnComNotImplemented();
    1824 #else
    1825     LogFlowThisFuncEnter();
    1826 
    1827     AutoCaller autoCaller(this);
    1828     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    1829 
    1830     ReturnComNotImplemented();
     1855STDMETHODIMP GuestSession::DirectoryOpen(IN_BSTR aPath, IN_BSTR aFilter, ComSafeArrayIn(DirectoryOpenFlag_T, aFlags), IGuestDirectory **aDirectory)
     1856{
     1857#ifndef VBOX_WITH_GUEST_CONTROL
     1858    ReturnComNotImplemented();
     1859#else
     1860    LogFlowThisFuncEnter();
     1861
     1862    if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
     1863        return setError(E_INVALIDARG, tr("No directory to open specified"));
     1864    if (RT_UNLIKELY((aFilter) != NULL && *(aFilter) != '\0'))
     1865        return setError(E_INVALIDARG, tr("Directory filters not implemented yet"));
     1866
     1867    CheckComArgOutPointerValid(aDirectory);
     1868
     1869    AutoCaller autoCaller(this);
     1870    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     1871
     1872    uint32_t fFlags = DirectoryOpenFlag_None;
     1873    if (aFlags)
     1874    {
     1875        com::SafeArray<DirectoryOpenFlag_T> flags(ComSafeArrayInArg(aFlags));
     1876        for (size_t i = 0; i < flags.size(); i++)
     1877            fFlags |= flags[i];
     1878
     1879        if (fFlags)
     1880            return setError(E_INVALIDARG, tr("Open flags (%#x) not implemented yet"), fFlags);
     1881    }
     1882
     1883    HRESULT hr = S_OK;
     1884
     1885    ComObjPtr <GuestDirectory> pDirectory;
     1886    int rc = directoryOpenInternal(Utf8Str(aPath), Utf8Str(aFilter), fFlags, pDirectory);
     1887    if (RT_SUCCESS(rc))
     1888    {
     1889        if (aDirectory)
     1890        {
     1891            /* Return directory object to the caller. */
     1892            hr = pDirectory.queryInterfaceTo(aDirectory);
     1893        }
     1894        else
     1895        {
     1896            rc = directoryClose(pDirectory);
     1897            if (RT_FAILURE(rc))
     1898                hr = setError(VBOX_E_IPRT_ERROR, tr("Unable to close directory object, rc=%Rrc"), rc);
     1899        }
     1900    }
     1901    else
     1902    {
     1903        switch (rc)
     1904        {
     1905            case VERR_INVALID_PARAMETER:
     1906               hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory failed: Invalid parameters given"));
     1907               break;
     1908
     1909            case VERR_BROKEN_PIPE:
     1910               hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory failed: Unexpectedly aborted"));
     1911               break;
     1912
     1913            default:
     1914               hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory failed: %Rrc"), rc);
     1915               break;
     1916        }
     1917    }
     1918
     1919    return hr;
    18311920#endif /* VBOX_WITH_GUEST_CONTROL */
    18321921}
     
    21032192        LogFlowThisFunc(("rc=%Rrc, cbRead=%RU32, cbStreamOut=%RU32\n",
    21042193                         rc, cbRead, streamOut.GetSize()));
    2105     } 
     2194    }
    21062195
    21072196    if (RT_FAILURE(rc))
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