VirtualBox

Changeset 49349 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Oct 31, 2013 4:40:46 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
90367
Message:

Guest Control:

  • Implemented IGuestSession::DirectoryRemove, IGuestSession::DirectoryRemoveRecursive, IGuestSession::DirectoryRename + IGuestSession::FileRename.
  • Added appropriate commands to VBoxManage (basic support for now).
  • Implemented support for proper guest session process termination via SCM.
  • Implemented support for internal anonymous wait events which are not relying on the public API's VBoxEventType_T.
  • Various bugfixes.
Location:
trunk/src/VBox/Main/src-client
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r48342 r49349  
    297297                    break;
    298298
    299                 case GUEST_SESSION_NOTIFY:
    300                     rc = pSession->dispatchToThis(pCtxCb, pSvcCb);
    301                     break;
    302 
    303299                case GUEST_EXEC_STATUS:
    304300                case GUEST_EXEC_OUTPUT:
     
    312308                    break;
    313309
     310                case GUEST_SESSION_NOTIFY:
     311                    rc = pSession->dispatchToThis(pCtxCb, pSvcCb);
     312                    break;
     313
    314314                default:
    315                     rc = VERR_NOT_SUPPORTED;
     315                    rc = pSession->dispatchToObject(pCtxCb, pSvcCb);
     316                    if (rc == VERR_NOT_FOUND)
     317                    {
     318                        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     319
     320                        rc = pSession->dispatchGeneric(pCtxCb, pSvcCb);
     321                    }
     322#ifndef DEBUG_andy
     323                    if (rc == VERR_NOT_IMPLEMENTED)
     324                        AssertMsgFailed(("Received not handled function %RU32\n", pCtxCb->uFunction));
     325#endif
    316326                    break;
    317327            }
     
    323333        rc = VERR_NOT_FOUND;
    324334
    325     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
     335    LogFlowFuncLeaveRC(rc);
    326336    return rc;
    327337}
     
    329339int Guest::sessionRemove(GuestSession *pSession)
    330340{
     341    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     342
    331343    LogFlowThisFuncEnter();
    332344
     
    364376    }
    365377
    366     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
     378    LogFlowFuncLeaveRC(rc);
    367379    return rc;
    368380}
     
    445457    }
    446458
    447     LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
     459    LogFlowFuncLeaveRC(rc);
    448460    return rc;
    449461}
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r47627 r49349  
    680680
    681681/**
    682  * Returns the current offset of the parser within
    683  * the internal data buffer.
    684  *
    685  * @return  uint32_t            Parser offset.
    686  */
    687 uint32_t GuestProcessStream::GetOffset()
    688 {
    689     return m_cbOffset;
    690 }
    691 
    692 uint32_t GuestProcessStream::GetSize()
    693 {
    694     return m_cbSize;
    695 }
    696 
    697 /**
    698682 * Tries to parse the next upcoming pair block within the internal
    699683 * buffer.
     
    814798    if (RT_SUCCESS(rc))
    815799    {
    816         GuestWaitEventTypes::iterator itEventTypes = mWaitEvents.begin();
    817         while (itEventTypes != mWaitEvents.end())
    818         {
    819             GuestWaitEvents::iterator itEvents = itEventTypes->second.begin();
    820             while (itEvents != itEventTypes->second.end())
     800        GuestEventGroup::iterator itEventGroups = mWaitEventGroups.begin();
     801        while (itEventGroups != mWaitEventGroups.end())
     802        {
     803            GuestWaitEvents::iterator itEvents = itEventGroups->second.begin();
     804            while (itEvents != itEventGroups->second.end())
    821805            {
    822                 GuestWaitEvent *pEvent = (*itEvents);
     806                GuestWaitEvent *pEvent = itEvents->second;
    823807                AssertPtr(pEvent);
    824808
    825809                /*
    826                  * Just cancel the event and remove it from the wait events
    827                  * map. Don't delete it though, this (hopefully) is done by
    828                  * the caller using unregisterWaitEvent().
     810                 * Just cancel the event, but don't remove it from the
     811                 * wait events map. Don't delete it though, this (hopefully)
     812                 * is done by the caller using unregisterWaitEvent().
    829813                 */
    830                 int rc2 = pEvent->Signal(NULL /* Cancel */);
     814                int rc2 = pEvent->Cancel();
    831815                AssertRC(rc2);
    832                 itEvents = itEventTypes->second.erase(itEvents);
     816
     817                itEvents++;
    833818            }
    834819
    835             mWaitEvents.erase(itEventTypes);
    836             itEventTypes = mWaitEvents.begin();
     820            itEventGroups++;
    837821        }
    838822
     
    846830}
    847831
     832int GuestBase::dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
     833{
     834    LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
     835
     836    AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER);
     837    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     838
     839    int vrc = VINF_SUCCESS;
     840
     841    try
     842    {
     843        LogFlowFunc(("uFunc=%RU32, cParms=%RU32\n",
     844                     pCtxCb->uFunction, pSvcCb->mParms));
     845
     846        switch (pCtxCb->uFunction)
     847        {
     848            case GUEST_MSG_PROGRESS_UPDATE:
     849                break;
     850
     851            case GUEST_MSG_REPLY:
     852            {
     853                if (pSvcCb->mParms >= 3)
     854                {
     855                    int idx = 1; /* Current parameter index. */
     856                    CALLBACKDATA_MSG_REPLY dataCb;
     857                    /* pSvcCb->mpaParms[0] always contains the context ID. */
     858                    vrc = pSvcCb->mpaParms[idx++].getUInt32(&dataCb.uType);
     859                    AssertRCReturn(vrc, vrc);
     860                    vrc = pSvcCb->mpaParms[idx++].getUInt32(&dataCb.rc);
     861                    AssertRCReturn(vrc, vrc);
     862                    vrc = pSvcCb->mpaParms[idx++].getPointer(&dataCb.pvPayload, &dataCb.cbPayload);
     863                    AssertRCReturn(vrc, vrc);
     864
     865                    GuestWaitEventPayload evPayload(dataCb.uType, dataCb.pvPayload, dataCb.cbPayload);
     866                    int rc2 = signalWaitEventInternal(pCtxCb, dataCb.rc, &evPayload);
     867                    AssertRC(rc2);
     868                }
     869                else
     870                    vrc = VERR_INVALID_PARAMETER;
     871                break;
     872            }
     873
     874            default:
     875                vrc = VERR_NOT_SUPPORTED;
     876                break;
     877        }
     878    }
     879    catch (std::bad_alloc)
     880    {
     881        vrc = VERR_NO_MEMORY;
     882    }
     883    catch (int rc)
     884    {
     885        vrc = rc;
     886    }
     887
     888    LogFlowFuncLeaveRC(vrc);
     889    return vrc;
     890}
     891
    848892int GuestBase::generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID)
    849893{
     
    869913
    870914int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
    871                                  const std::list<VBoxEventType_T> &lstEvents,
     915                                 GuestWaitEvent **ppEvent)
     916{
     917    GuestEventTypes eventTypesEmpty;
     918    return registerWaitEvent(uSessionID, uObjectID, eventTypesEmpty, ppEvent);
     919}
     920
     921int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
     922                                 const GuestEventTypes &lstEvents,
    872923                                 GuestWaitEvent **ppEvent)
    873924{
     
    887938            AssertPtr(pEvent);
    888939
    889             for (std::list<VBoxEventType_T>::const_iterator itEvents = lstEvents.begin();
     940            /* Insert event into matching event group. This is for faster per-group
     941             * lookup of all events later. */
     942            for (GuestEventTypes::const_iterator itEvents = lstEvents.begin();
    890943                 itEvents != lstEvents.end(); itEvents++)
    891944            {
    892                 mWaitEvents[(*itEvents)].push_back(pEvent);
     945                mWaitEventGroups[(*itEvents)].insert(
     946                   std::pair<uint32_t, GuestWaitEvent*>(uContextID, pEvent));
     947                /** @todo Check for key collision. */
    893948            }
     949
     950            /* Register event in regular event list. */
     951            /** @todo Check for key collisions. */
     952            mWaitEvents[uContextID] = pEvent;
    894953
    895954            *ppEvent = pEvent;
     
    908967}
    909968
    910 int GuestBase::signalWaitEvents(VBoxEventType_T aType, IEvent *aEvent)
     969int GuestBase::signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent)
    911970{
    912971    int rc = RTCritSectEnter(&mWaitEventCritSect);
     972#ifdef DEBUG
     973    uint32_t cEvents = 0;
     974#endif
    913975    if (RT_SUCCESS(rc))
    914976    {
    915         GuestWaitEventTypes::iterator itTypes = mWaitEvents.find(aType);
    916         if (itTypes != mWaitEvents.end())
    917         {
    918             for (GuestWaitEvents::iterator itEvents = itTypes->second.begin();
    919                  itEvents != itTypes->second.end(); itEvents++)
     977        GuestEventGroup::iterator itGroups = mWaitEventGroups.find(aType);
     978        if (itGroups != mWaitEventGroups.end())
     979        {
     980            for (GuestWaitEvents::iterator itEvents = itGroups->second.begin();
     981                 itEvents != itGroups->second.end(); itEvents++)
    920982            {
    921                 LogFlowThisFunc(("Signalling event=%p with type=%ld ...\n",
    922                                  (*itEvents), aType));
    923 
     983#ifdef DEBUG
     984                LogFlowThisFunc(("Signalling event=%p, type=%ld (CID %RU32: Sesion=%RU32, Object=%RU32, Count=%RU32) ...\n",
     985                                 itEvents->second, aType, itEvents->first,
     986                                 VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(itEvents->first),
     987                                 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(itEvents->first),
     988                                 VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(itEvents->first)));
     989#endif
    924990                ComPtr<IEvent> pThisEvent = aEvent;
    925991                Assert(!pThisEvent.isNull());
    926                 int rc2 = (*itEvents)->Signal(aEvent);
     992                int rc2 = itEvents->second->SignalExternal(aEvent);
    927993                if (RT_SUCCESS(rc))
    928994                    rc = rc2;
     995#ifdef DEBUG
     996                cEvents++;
     997#endif
    929998            }
    930999        }
     
    9351004    }
    9361005
    937     return rc;
     1006#ifdef DEBUG
     1007    LogFlowThisFunc(("Signalled %RU32 events, rc=%Rrc\n", cEvents, rc));
     1008#endif
     1009    return rc;
     1010}
     1011
     1012int GuestBase::signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx,
     1013                                       int guestRc, const GuestWaitEventPayload *pPayload)
     1014{
     1015    if (RT_SUCCESS(guestRc))
     1016        return signalWaitEventInternalEx(pCbCtx, VINF_SUCCESS,
     1017                                         0 /* Guest rc */, pPayload);
     1018
     1019    return signalWaitEventInternalEx(pCbCtx, VERR_GSTCTL_GUEST_ERROR,
     1020                                     guestRc, pPayload);
     1021}
     1022
     1023int GuestBase::signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx,
     1024                                         int rc, int guestRc,
     1025                                         const GuestWaitEventPayload *pPayload)
     1026{
     1027    AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
     1028    /* pPayload is optional. */
     1029
     1030    int rc2;
     1031    GuestWaitEvents::iterator itEvent = mWaitEvents.find(pCbCtx->uContextID);
     1032    if (itEvent != mWaitEvents.end())
     1033    {
     1034        LogFlowThisFunc(("Signalling event=%p (CID %RU32, rc=%Rrc, guestRc=%Rrc, pPayload=%p) ...\n",
     1035                         itEvent->second, itEvent->first, rc, guestRc, pPayload));
     1036        GuestWaitEvent *pEvent = itEvent->second;
     1037        AssertPtr(pEvent);
     1038        rc2 = pEvent->SignalInternal(rc, guestRc, pPayload);
     1039    }
     1040    else
     1041        rc2 = VERR_NOT_FOUND;
     1042
     1043    return rc2;
    9381044}
    9391045
     
    9461052    if (RT_SUCCESS(rc))
    9471053    {
    948         const std::list<VBoxEventType_T> lstTypes = pEvent->Types();
    949         for (std::list<VBoxEventType_T>::const_iterator itEvents = lstTypes.begin();
     1054        const GuestEventTypes lstTypes = pEvent->Types();
     1055        for (GuestEventTypes::const_iterator itEvents = lstTypes.begin();
    9501056             itEvents != lstTypes.end(); itEvents++)
    9511057        {
    9521058            /** @todo Slow O(n) lookup. Optimize this. */
    953             GuestWaitEvents::iterator itCurEvent = mWaitEvents[(*itEvents)].begin();
    954             while (itCurEvent != mWaitEvents[(*itEvents)].end())
     1059            GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itEvents)].begin();
     1060            while (itCurEvent != mWaitEventGroups[(*itEvents)].end())
    9551061            {
    956              if ((*itCurEvent) == pEvent)
     1062             if (itCurEvent->second == pEvent)
    9571063             {
    958                  itCurEvent = mWaitEvents[(*itEvents)].erase(itCurEvent);
     1064                 itCurEvent = mWaitEventGroups[(*itEvents)].erase(itCurEvent);
    9591065                 break;
    9601066             }
     
    9731079}
    9741080
     1081/**
     1082 * Waits for a formerly registered guest event.
     1083 *
     1084 * @return  IPRT status code.
     1085 * @param   pEvent                  Pointer to event to wait for.
     1086 * @param   uTimeoutMS              Timeout (in ms) for waiting.
     1087 * @param   pType                   Event type of following IEvent.
     1088 *                                  Optional.
     1089 * @param   ppEvent                 Pointer to IEvent which got triggered
     1090 *                                  for this event. Optional.
     1091 */
    9751092int GuestBase::waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
    9761093                            VBoxEventType_T *pType, IEvent **ppEvent)
    9771094{
    9781095    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     1096    /* pType is optional. */
     1097    /* ppEvent is optional. */
    9791098
    9801099    int vrc = pEvent->Wait(uTimeoutMS);
     
    9821101    {
    9831102        const ComPtr<IEvent> pThisEvent = pEvent->Event();
    984         Assert(!pThisEvent.isNull());
    985 
    986         if (pType)
    987         {
    988             HRESULT hr = pThisEvent->COMGETTER(Type)(pType);
    989             if (FAILED(hr))
    990                 vrc = VERR_COM_UNEXPECTED;
    991         }
    992         if (   RT_SUCCESS(vrc)
    993             && ppEvent)
    994             pThisEvent.queryInterfaceTo(ppEvent);
    995 
    996         unconst(pThisEvent).setNull();
     1103        if (!pThisEvent.isNull()) /* Having a VBoxEventType_ event is optional. */
     1104        {
     1105            if (pType)
     1106            {
     1107                HRESULT hr = pThisEvent->COMGETTER(Type)(pType);
     1108                if (FAILED(hr))
     1109                    vrc = VERR_COM_UNEXPECTED;
     1110            }
     1111            if (   RT_SUCCESS(vrc)
     1112                && ppEvent)
     1113                pThisEvent.queryInterfaceTo(ppEvent);
     1114
     1115            unconst(pThisEvent).setNull();
     1116        }
    9971117    }
    9981118
     
    10221142}
    10231143
    1024 int GuestObject::registerWaitEvent(const std::list<VBoxEventType_T> &lstEvents,
     1144int GuestObject::registerWaitEvent(const GuestEventTypes &lstEvents,
    10251145                                   GuestWaitEvent **ppEvent)
    10261146{
     
    10581178}
    10591179
    1060 GuestWaitEvent::GuestWaitEvent(uint32_t uCID,
    1061                                const std::list<VBoxEventType_T> &lstEvents)
    1062     : fAborted(false),
    1063       mCID(uCID),
    1064       mEventTypes(lstEvents),
    1065       mEventSem(NIL_RTSEMEVENT)
    1066 {
    1067     int rc = RTSemEventCreate(&mEventSem);
    1068     AssertRC(rc);
    1069     /** @todo Throw an exception on failure! */
    1070 }
    1071 
    1072 GuestWaitEvent::~GuestWaitEvent(void)
    1073 {
    1074 }
    1075 
    1076 /**
    1077  * Signals the event. Passing NULL will abort (cancel)
    1078  * the event.
    1079  *
    1080  * @return  IPRT status code.
    1081  * @param   pEvent              IEvent to associate.
    1082  */
    1083 int GuestWaitEvent::Signal(IEvent *pEvent)
    1084 {
    1085     AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
    1086 
    1087     if (pEvent)
    1088         mEvent = pEvent;
     1180GuestWaitEventBase::GuestWaitEventBase(void)
     1181    : mCID(0),
     1182      mEventSem(NIL_RTSEMEVENT),
     1183      mfAborted(false),
     1184      mRc(VINF_SUCCESS),
     1185      mGuestRc(VINF_SUCCESS)
     1186{
     1187}
     1188
     1189GuestWaitEventBase::~GuestWaitEventBase(void)
     1190{
     1191}
     1192
     1193int GuestWaitEventBase::Init(uint32_t uCID)
     1194{
     1195    mCID = uCID;
     1196
     1197    return RTSemEventCreate(&mEventSem);
     1198}
     1199
     1200int GuestWaitEventBase::SignalInternal(int rc, int guestRc,
     1201                                       const GuestWaitEventPayload *pPayload)
     1202{
     1203    AssertReturn(!mfAborted, VERR_CANCELLED);
     1204
     1205#ifdef VBOX_STRICT
     1206    if (rc == VERR_GSTCTL_GUEST_ERROR)
     1207        AssertMsg(RT_FAILURE(guestRc), ("Guest error indicated but no actual guest error set (%Rrc)\n", guestRc));
    10891208    else
    1090         ASMAtomicWriteBool(&fAborted, true);
    1091 
    1092     return RTSemEventSignal(mEventSem);
    1093 }
    1094 
    1095 int GuestWaitEvent::Wait(RTMSINTERVAL uTimeoutMS)
     1209        AssertMsg(RT_SUCCESS(guestRc), ("No guest error indicated but actual guest error set (%Rrc)\n", guestRc));
     1210#endif
     1211
     1212    int rc2;
     1213    if (pPayload)
     1214        rc2 = mPayload.CopyFromDeep(*pPayload);
     1215    else
     1216        rc2 = VINF_SUCCESS;
     1217    if (RT_SUCCESS(rc2))
     1218    {
     1219        mRc = rc;
     1220        mGuestRc = guestRc;
     1221
     1222        rc2 = RTSemEventSignal(mEventSem);
     1223    }
     1224
     1225    return rc2;
     1226}
     1227
     1228int GuestWaitEventBase::Wait(RTMSINTERVAL uTimeoutMS)
    10961229{
    10971230    int rc = VINF_SUCCESS;
    10981231
    1099     if (ASMAtomicReadBool(&fAborted))
     1232    if (ASMAtomicReadBool(&mfAborted))
    11001233        rc = VERR_CANCELLED;
    11011234
     
    11081241            msInterval = RT_INDEFINITE_WAIT;
    11091242        rc = RTSemEventWait(mEventSem, msInterval);
    1110         if (ASMAtomicReadBool(&fAborted))
     1243        if (ASMAtomicReadBool(&mfAborted))
    11111244            rc = VERR_CANCELLED;
    1112     }
    1113 
    1114     return rc;
    1115 }
    1116 
     1245        if (RT_SUCCESS(rc))
     1246        {
     1247            /* If waiting succeeded, return the overall
     1248             * result code. */
     1249            rc = mRc;
     1250        }
     1251    }
     1252
     1253    return rc;
     1254}
     1255
     1256GuestWaitEvent::GuestWaitEvent(uint32_t uCID,
     1257                               const GuestEventTypes &lstEvents)
     1258{
     1259    int rc2 = Init(uCID);
     1260    AssertRC(rc2); /** @todo Throw exception here. */
     1261
     1262    mEventTypes = lstEvents;
     1263}
     1264
     1265GuestWaitEvent::GuestWaitEvent(uint32_t uCID)
     1266{
     1267    int rc2 = Init(uCID);
     1268    AssertRC(rc2); /** @todo Throw exception here. */
     1269}
     1270
     1271GuestWaitEvent::~GuestWaitEvent(void)
     1272{
     1273
     1274}
     1275
     1276/**
     1277 * Cancels the event.
     1278 */
     1279int GuestWaitEvent::Cancel(void)
     1280{
     1281    AssertReturn(!mfAborted, VERR_CANCELLED);
     1282    ASMAtomicWriteBool(&mfAborted, true);
     1283
     1284    return RTSemEventSignal(mEventSem);
     1285}
     1286
     1287int GuestWaitEvent::Init(uint32_t uCID)
     1288{
     1289    return GuestWaitEventBase::Init(uCID);
     1290}
     1291
     1292/**
     1293 * Signals the event.
     1294 *
     1295 * @return  IPRT status code.
     1296 * @param   pEvent              Public IEvent to associate.
     1297 *                              Optional.
     1298 */
     1299int GuestWaitEvent::SignalExternal(IEvent *pEvent)
     1300{
     1301    AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
     1302
     1303    if (pEvent)
     1304        mEvent = pEvent;
     1305
     1306    return RTSemEventSignal(mEventSem);
     1307}
     1308
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r47627 r49349  
    5959/////////////////////////////////////////////////////////////////////////////
    6060
    61 int GuestDirectory::init(GuestSession *aSession,
    62                          const Utf8Str &strPath, const Utf8Str &strFilter, uint32_t uFlags)
    63 {
    64     LogFlowThisFunc(("strPath=%s, strFilter=%s, uFlags=%x\n",
    65                      strPath.c_str(), strFilter.c_str(), uFlags));
     61int GuestDirectory::init(Console *pConsole, GuestSession *pSession,
     62                         ULONG uDirID, const GuestDirectoryOpenInfo &openInfo)
     63{
     64    LogFlowThisFunc(("pConsole=%p, pSession=%p, uDirID=%RU32, strPath=%s, strFilter=%s, uFlags=%x\n",
     65                     pConsole, pSession, uDirID, openInfo.mPath.c_str(), openInfo.mFilter.c_str(),
     66                     openInfo.mFlags));
     67
     68    AssertPtrReturn(pConsole, VERR_INVALID_POINTER);
     69    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    6670
    6771    /* Enclose the state transition NotReady->InInit->Ready. */
     
    6973    AssertReturn(autoInitSpan.isOk(), E_FAIL);
    7074
    71     mData.mSession = aSession;
    72     mData.mName    = strPath;
    73     mData.mFilter  = strFilter;
    74     mData.mFlags   = uFlags;
    75 
    76     /* Start the directory process on the guest. */
    77     GuestProcessStartupInfo procInfo;
    78     procInfo.mName      = Utf8StrFmt(tr("Reading directory \"%s\"", strPath.c_str()));
    79     procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_LS);
    80     procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
    81     procInfo.mFlags     = ProcessCreateFlag_WaitForStdOut;
    82 
    83     procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    84     /* We want the long output format which contains all the object details. */
    85     procInfo.mArguments.push_back(Utf8Str("-l"));
     75#ifndef VBOX_WITH_GUEST_CONTROL
     76    autoInitSpan.setSucceeded();
     77    return VINF_SUCCESS;
     78#else
     79    int vrc = bindToSession(pConsole, pSession, uDirID /* Object ID */);
     80    if (RT_SUCCESS(vrc))
     81    {
     82        mSession = pSession;
     83
     84        mData.mID = uDirID;
     85        mData.mOpenInfo = openInfo;
     86    }
     87
     88    if (RT_SUCCESS(vrc))
     89    {
     90        /* Start the directory process on the guest. */
     91        GuestProcessStartupInfo procInfo;
     92        procInfo.mName      = Utf8StrFmt(tr("Reading directory \"%s\"", openInfo.mPath.c_str()));
     93        procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_LS);
     94        procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
     95        procInfo.mFlags     = ProcessCreateFlag_WaitForStdOut;
     96
     97        procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     98        /* We want the long output format which contains all the object details. */
     99        procInfo.mArguments.push_back(Utf8Str("-l"));
    86100#if 0 /* Flags are not supported yet. */
    87     if (uFlags & DirectoryOpenFlag_NoSymlinks)
    88         procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
     101        if (uFlags & DirectoryOpenFlag_NoSymlinks)
     102            procInfo.mArguments.push_back(Utf8Str("--nosymlinks")); /** @todo What does GNU here? */
    89103#endif
    90     /** @todo Recursion support? */
    91     procInfo.mArguments.push_back(strPath); /* The directory we want to open. */
    92 
    93     /*
    94      * Start the process asynchronously and keep it around so that we can use
    95      * it later in subsequent read() calls.
    96      * Note: No guest rc available because operation is asynchronous.
    97      */
    98     int rc = mData.mProcessTool.Init(mData.mSession, procInfo,
    99                                      true /* Async */, NULL /* Guest rc */);
    100     if (RT_SUCCESS(rc))
     104        /** @todo Recursion support? */
     105        procInfo.mArguments.push_back(openInfo.mPath); /* The directory we want to open. */
     106
     107        /*
     108         * Start the process asynchronously and keep it around so that we can use
     109         * it later in subsequent read() calls.
     110         * Note: No guest rc available because operation is asynchronous.
     111         */
     112        vrc = mData.mProcessTool.Init(mSession, procInfo,
     113                                      true /* Async */, NULL /* Guest rc */);
     114    }
     115
     116    if (RT_SUCCESS(vrc))
    101117    {
    102118        /* Confirm a successful initialization when it's the case. */
    103119        autoInitSpan.setSucceeded();
    104         return rc;
    105     }
    106 
    107     autoInitSpan.setFailed();
    108     return rc;
     120        return vrc;
     121    }
     122    else
     123        autoInitSpan.setFailed();
     124
     125    return vrc;
     126#endif /* VBOX_WITH_GUEST_CONTROL */
    109127}
    110128
     
    139157    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    140158
    141     mData.mName.cloneTo(aName);
     159    mData.mOpenInfo.mPath.cloneTo(aName);
    142160
    143161    return S_OK;
     
    155173    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    156174
    157     mData.mFilter.cloneTo(aFilter);
     175    mData.mOpenInfo.mFilter.cloneTo(aFilter);
    158176
    159177    return S_OK;
     
    162180// private methods
    163181/////////////////////////////////////////////////////////////////////////////
     182
     183int GuestDirectory::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
     184{
     185    AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
     186    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     187
     188    LogFlowThisFunc(("strPath=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
     189                     mData.mOpenInfo.mPath.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
     190
     191    int vrc;
     192    switch (pCbCtx->uFunction)
     193    {
     194        case GUEST_DIR_NOTIFY:
     195        {
     196            int idx = 1; /* Current parameter index. */
     197            CALLBACKDATA_DIR_NOTIFY dataCb;
     198            /* pSvcCb->mpaParms[0] always contains the context ID. */
     199            pSvcCb->mpaParms[idx++].getUInt32(&dataCb.uType);
     200            pSvcCb->mpaParms[idx++].getUInt32(&dataCb.rc);
     201
     202            int guestRc = (int)dataCb.rc; /* uint32_t vs. int. */
     203
     204            LogFlowFunc(("uType=%RU32, guestRc=%Rrc\n",
     205                         dataCb.uType, guestRc));
     206
     207            switch (dataCb.uType)
     208            {
     209                /* Nothing here yet, nothing to dispatch further. */
     210
     211                default:
     212                    vrc = VERR_NOT_SUPPORTED;
     213                    break;
     214            }
     215            break;
     216        }
     217
     218        default:
     219            /* Silently ignore not implemented functions. */
     220            vrc = VERR_NOT_SUPPORTED;
     221            break;
     222    }
     223
     224#ifdef DEBUG
     225    LogFlowFuncLeaveRC(vrc);
     226#endif
     227    return vrc;
     228}
     229
     230/* static */
     231Utf8Str GuestDirectory::guestErrorToString(int guestRc)
     232{
     233    Utf8Str strError;
     234
     235    /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
     236    switch (guestRc)
     237    {
     238        case VERR_DIR_NOT_EMPTY:
     239            strError += Utf8StrFmt("Directoy is not empty");
     240            break;
     241
     242        default:
     243            strError += Utf8StrFmt("%Rrc", guestRc);
     244            break;
     245    }
     246
     247    return strError;
     248}
     249
     250/* static */
     251HRESULT GuestDirectory::setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
     252{
     253    AssertPtr(pInterface);
     254    AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
     255
     256    return pInterface->setError(VBOX_E_IPRT_ERROR, GuestDirectory::guestErrorToString(guestRc).c_str());
     257}
    164258
    165259// implementation of public methods
     
    176270    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    177271
    178     AssertPtr(mData.mSession);
    179     int rc = mData.mSession->directoryRemoveFromList(this);
     272    AssertPtr(mSession);
     273    int rc = mSession->directoryRemoveFromList(this);
    180274    AssertRC(rc);
    181275
     
    188282        switch (rc)
    189283        {
    190            case VERR_GSTCTL_GUEST_ERROR:
     284            case VERR_GSTCTL_GUEST_ERROR:
    191285                hr = GuestProcess::setErrorExternal(this, guestRc);
    192286                break;
     
    200294                hr = setError(VBOX_E_IPRT_ERROR,
    201295                              tr("Terminating open guest directory \"%s\" failed: %Rrc"),
    202                               mData.mName.c_str(), rc);
     296                              mData.mOpenInfo.mPath.c_str(), rc);
    203297                break;
    204298        }
     
    293387            case VERR_ACCESS_DENIED:
    294388                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Unable to read / access denied"),
    295                               mData.mName.c_str());
     389                              mData.mOpenInfo.mPath.c_str());
    296390                break;
    297391
    298392            case VERR_PATH_NOT_FOUND:
    299393                hr = setError(VBOX_E_IPRT_ERROR, tr("Reading directory \"%s\" failed: Path not found"),
    300                               mData.mName.c_str());
     394                              mData.mOpenInfo.mPath.c_str());
    301395                break;
    302396
     
    304398                /* See SDK reference. */
    305399                hr = setError(VBOX_E_OBJECT_NOT_FOUND, tr("No more entries for directory \"%s\""),
    306                               mData.mName.c_str());
     400                              mData.mOpenInfo.mPath.c_str());
    307401                break;
    308402
    309403            default:
    310404                hr = setError(VBOX_E_IPRT_ERROR, tr("Error while reading directory \"%s\": %Rrc\n"),
    311                               mData.mName.c_str(), rc);
     405                              mData.mOpenInfo.mPath.c_str(), rc);
    312406                break;
    313407        }
  • trunk/src/VBox/Main/src-client/GuestFileImpl.cpp

    r49006 r49349  
    7777            {
    7878                Assert(!mFile.isNull());
    79                 int rc2 = mFile->signalWaitEvents(aType, aEvent);
     79                int rc2 = mFile->signalWaitEvent(aType, aEvent);
    8080#ifdef DEBUG_andy
    8181                LogFlowFunc(("Signalling events of type=%ld, file=%p resulted in rc=%Rrc\n",
     
    411411int GuestFile::callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
    412412{
    413 #ifdef DEBUG
     413    AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
     414    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     415
    414416    LogFlowThisFunc(("strName=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
    415417                     mData.mOpenInfo.mFileName.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
    416 #endif
    417     AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
    418418
    419419    int vrc;
     
    447447
    448448    GuestWaitEvent *pEvent = NULL;
    449     std::list < VBoxEventType_T > eventTypes;
     449    GuestEventTypes eventTypes;
    450450    try
    451451    {
     
    539539        AssertRC(rc2);
    540540
     541        rc2 = signalWaitEventInternal(pCbCtx,
     542                                      guestRc, NULL /* pPayload */);
     543        AssertRC(rc2);
     544
    541545        return VINF_SUCCESS; /* Report to the guest. */
    542546    }
     
    548552            int rc2 = setFileStatus(FileStatus_Error, guestRc);
    549553            AssertRC(rc2);
     554
    550555            break;
    551556        }
     
    561566                    AssertMsg(mData.mID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID),
    562567                              ("File ID %RU32 does not match context ID %RU32\n", mData.mID,
    563                                VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID)));
     568                              VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID)));
    564569
    565570                    /* Set the initial offset. On the guest the whole opening operation
     
    570575                /* Set the process status. */
    571576                int rc2 = setFileStatus(FileStatus_Open, guestRc);
    572                 if (RT_SUCCESS(vrc))
    573                     vrc = rc2;
     577                AssertRC(rc2);
    574578            }
    575579            else
     
    678682    }
    679683
     684    if (RT_SUCCESS(vrc))
     685    {
     686        GuestWaitEventPayload payload(dataCb.uType, &dataCb, sizeof(dataCb));
     687        int rc2 = signalWaitEventInternal(pCbCtx, guestRc, &payload);
     688        AssertRC(rc2);
     689    }
     690
    680691    LogFlowThisFunc(("uType=%RU32, guestRc=%Rrc\n",
    681692                     dataCb.uType, dataCb.rc));
     
    708719
    709720    GuestWaitEvent *pEvent = NULL;
    710     std::list < VBoxEventType_T > eventTypes;
     721    GuestEventTypes eventTypes;
    711722    try
    712723    {
     
    765776
    766777    GuestWaitEvent *pEvent = NULL;
    767     std::list < VBoxEventType_T > eventTypes;
     778    GuestEventTypes eventTypes;
    768779    try
    769780    {
     
    820831
    821832    GuestWaitEvent *pEvent = NULL;
    822     std::list < VBoxEventType_T > eventTypes;
     833    GuestEventTypes eventTypes;
    823834    try
    824835    {
     
    876887
    877888    GuestWaitEvent *pEvent = NULL;
    878     std::list < VBoxEventType_T > eventTypes;
     889    GuestEventTypes eventTypes;
    879890    try
    880891    {
     
    970981    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    971982
    972     VBoxEventType_T evtType;
    973     ComPtr<IEvent> pIEvent;
    974983    int vrc = waitForEvent(pEvent, uTimeoutMS,
    975                            &evtType, pIEvent.asOutParam());
    976     if (RT_SUCCESS(vrc))
    977     {
    978         if (evtType == VBoxEventType_OnGuestFileOffsetChanged)
    979         {
    980             if (puOffset)
    981             {
    982                 ComPtr<IGuestFileOffsetChangedEvent> pFileEvent = pIEvent;
    983                 Assert(!pFileEvent.isNull());
    984 
    985                 HRESULT hr = pFileEvent->COMGETTER(Offset)((LONG64*)puOffset);
    986                 ComAssertComRC(hr);
    987             }
     984                           NULL /* Event type */, NULL /* IEvent */);
     985    if (RT_SUCCESS(vrc))
     986    {
     987        Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
     988        const PCALLBACKDATA_FILE_NOTIFY pvCbData =
     989            (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
     990        Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_SEEK);
     991
     992        if (puOffset)
     993            *puOffset = pvCbData->u.seek.uOffActual;
     994    }
     995
     996    return vrc;
     997}
     998
     999int GuestFile::waitForRead(GuestWaitEvent *pEvent,
     1000                           uint32_t uTimeoutMS,
     1001                           void *pvData, size_t cbData, uint32_t *pcbRead)
     1002{
     1003    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     1004
     1005    int vrc = waitForEvent(pEvent, uTimeoutMS,
     1006                           NULL /* Event type */, NULL /* IEvent */);
     1007    if (RT_SUCCESS(vrc))
     1008    {
     1009        Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
     1010        const PCALLBACKDATA_FILE_NOTIFY pvCbData =
     1011            (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
     1012        Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_READ);
     1013
     1014        uint32_t cbRead = pvCbData->u.read.cbData;
     1015        if (   cbRead
     1016            && cbRead <= cbData)
     1017        {
     1018            memcpy(pvData,
     1019                   pvCbData->u.read.pvData, cbRead);
    9881020        }
    9891021        else
    990             vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
    991     }
    992 
    993     return vrc;
    994 }
    995 
    996 int GuestFile::waitForRead(GuestWaitEvent *pEvent,
    997                            uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead)
    998 {
    999     AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    1000 
    1001     VBoxEventType_T evtType;
    1002     ComPtr<IEvent> pIEvent;
    1003     int vrc = waitForEvent(pEvent, uTimeoutMS,
    1004                            &evtType, pIEvent.asOutParam());
    1005     if (RT_SUCCESS(vrc))
    1006     {
    1007         if (evtType == VBoxEventType_OnGuestFileRead)
    1008         {
    1009             ComPtr<IGuestFileReadEvent> pFileEvent = pIEvent;
    1010             Assert(!pFileEvent.isNull());
    1011 
    1012             HRESULT hr;
    1013             if (pvData)
    1014             {
    1015                 com::SafeArray <BYTE> data;
    1016                 hr = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
    1017                 ComAssertComRC(hr);
    1018                 size_t cbRead = data.size();
    1019                 if (   cbRead
    1020                     && cbRead <= cbData)
    1021                 {
    1022                     memcpy(pvData, data.raw(), data.size());
    1023                 }
    1024                 else
    1025                     vrc = VERR_BUFFER_OVERFLOW;
    1026             }
    1027             if (pcbRead)
    1028             {
    1029                 hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbRead);
    1030                 ComAssertComRC(hr);
    1031             }
    1032         }
    1033         else
    1034             vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
     1022            vrc = VERR_BUFFER_OVERFLOW;
     1023
     1024        if (pcbRead)
     1025            *pcbRead = cbRead;
    10351026    }
    10361027
     
    10421033{
    10431034    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    1044     /* pFileStatus is optional. */
    1045 
    1046     VBoxEventType_T evtType;
    1047     ComPtr<IEvent> pIEvent;
     1035
    10481036    int vrc = waitForEvent(pEvent, uTimeoutMS,
    1049                            &evtType, pIEvent.asOutParam());
    1050     if (RT_SUCCESS(vrc))
    1051     {
    1052         Assert(evtType == VBoxEventType_OnGuestFileStateChanged);
    1053         ComPtr<IGuestFileStateChangedEvent> pFileEvent = pIEvent;
    1054         Assert(!pFileEvent.isNull());
    1055 
    1056         HRESULT hr;
    1057         if (pFileStatus)
    1058         {
    1059             hr = pFileEvent->COMGETTER(Status)(pFileStatus);
    1060             ComAssertComRC(hr);
    1061         }
    1062 
    1063         ComPtr<IVirtualBoxErrorInfo> errorInfo;
    1064         hr = pFileEvent->COMGETTER(Error)(errorInfo.asOutParam());
    1065         ComAssertComRC(hr);
    1066 
    1067         LONG lGuestRc;
    1068         hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
    1069         ComAssertComRC(hr);
    1070 
    1071         LogFlowThisFunc(("resultDetail=%RI32 (rc=%Rrc)\n",
    1072                          lGuestRc, lGuestRc));
    1073 
    1074         if (RT_FAILURE((int)lGuestRc))
    1075             vrc = VERR_GSTCTL_GUEST_ERROR;
     1037                           NULL /* Event type */, NULL /* IEvent */);
     1038    if (RT_SUCCESS(vrc))
     1039    {
     1040        Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
     1041        const PCALLBACKDATA_FILE_NOTIFY pvCbData =
     1042            (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
     1043        /* Note: pvCbData->uType can be different types. */;
     1044
     1045
    10761046
    10771047        if (pGuestRc)
    1078             *pGuestRc = (int)lGuestRc;
     1048            *pGuestRc = pvCbData->rc; /* int vs. uint32_t */
    10791049    }
    10801050
     
    10871057    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    10881058
    1089     VBoxEventType_T evtType;
    1090     ComPtr<IEvent> pIEvent;
    10911059    int vrc = waitForEvent(pEvent, uTimeoutMS,
    1092                            &evtType, pIEvent.asOutParam());
    1093     if (RT_SUCCESS(vrc))
    1094     {
    1095         if (evtType == VBoxEventType_OnGuestFileWrite)
    1096         {
    1097             if (pcbWritten)
    1098             {
    1099                 ComPtr<IGuestFileWriteEvent> pFileEvent = pIEvent;
    1100                 Assert(!pFileEvent.isNull());
    1101 
    1102                 HRESULT hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbWritten);
    1103                 ComAssertComRC(hr);
    1104             }
    1105         }
    1106         else
    1107             vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
     1060                           NULL /* Event type */, NULL /* IEvent */);
     1061    if (RT_SUCCESS(vrc))
     1062    {
     1063        Assert(pEvent->Payload().Size() == sizeof(CALLBACKDATA_FILE_NOTIFY));
     1064        const PCALLBACKDATA_FILE_NOTIFY pvCbData =
     1065            (PCALLBACKDATA_FILE_NOTIFY)pEvent->Payload().Raw();
     1066        Assert(pvCbData->uType == GUEST_FILE_NOTIFYTYPE_WRITE);
     1067
     1068        if (pcbWritten)
     1069            *pcbWritten = pvCbData->u.write.cbWritten;
    11081070    }
    11091071
     
    11251087
    11261088    GuestWaitEvent *pEvent = NULL;
    1127     std::list < VBoxEventType_T > eventTypes;
     1089    GuestEventTypes eventTypes;
    11281090    try
    11291091    {
     
    11841146
    11851147    GuestWaitEvent *pEvent = NULL;
    1186     std::list < VBoxEventType_T > eventTypes;
     1148    GuestEventTypes eventTypes;
    11871149    try
    11881150    {
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r48770 r49349  
    116116            {
    117117                Assert(!mProcess.isNull());
    118                 int rc2 = mProcess->signalWaitEvents(aType, aEvent);
    119 #ifdef DEBUG_andy
     118                int rc2 = mProcess->signalWaitEvent(aType, aEvent);
     119#ifdef DEBUG
    120120                LogFlowThisFunc(("Signalling events of type=%ld, process=%p resulted in rc=%Rrc\n",
    121121                                 aType, mProcess, rc2));
     
    512512
    513513#ifdef DEBUG
    514     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     514    LogFlowFuncLeaveRC(vrc);
    515515#endif
    516516    return vrc;
     
    647647    int vrc = setProcessStatus(ProcessStatus_Down, VINF_SUCCESS);
    648648
    649     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     649    LogFlowFuncLeaveRC(vrc);
    650650    return vrc;
    651651}
     
    714714    }
    715715
    716     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     716    LogFlowFuncLeaveRC(vrc);
    717717    return vrc;
    718718}
     
    832832    }
    833833
    834     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     834    LogFlowFuncLeaveRC(vrc);
    835835    return vrc;
    836836}
     
    868868    }
    869869
    870     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     870    LogFlowFuncLeaveRC(vrc);
    871871    return vrc;
    872872}
     
    904904
    905905    GuestWaitEvent *pEvent = NULL;
    906     std::list < VBoxEventType_T > eventTypes;
     906    GuestEventTypes eventTypes;
    907907    try
    908908    {
     
    948948    unregisterWaitEvent(pEvent);
    949949
    950     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     950    LogFlowFuncLeaveRC(vrc);
    951951    return vrc;
    952952}
     
    10411041
    10421042    GuestWaitEvent *pEvent = NULL;
    1043     std::list < VBoxEventType_T > eventTypes;
     1043    GuestEventTypes eventTypes;
    10441044    try
    10451045    {
     
    11681168    unregisterWaitEvent(pEvent);
    11691169
    1170     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1170    LogFlowFuncLeaveRC(vrc);
    11711171    return vrc;
    11721172}
     
    12001200    }
    12011201
    1202     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1202    LogFlowFuncLeaveRC(vrc);
    12031203    return vrc;
    12041204}
     
    12501250    {
    12511251        GuestWaitEvent *pEvent = NULL;
    1252         std::list < VBoxEventType_T > eventTypes;
     1252        GuestEventTypes eventTypes;
    12531253        try
    12541254        {
     
    12791279    }
    12801280
    1281     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1281    LogFlowFuncLeaveRC(vrc);
    12821282    return vrc;
    12831283}
     
    12851285/* static */
    12861286ProcessWaitResult_T GuestProcess::waitFlagsToResultEx(uint32_t fWaitFlags,
    1287                                                       ProcessStatus_T procStatus, uint32_t uProcFlags,
    1288                                                       uint32_t uProtocol)
     1287                                                      ProcessStatus_T oldStatus, ProcessStatus_T newStatus,
     1288                                                      uint32_t uProcFlags, uint32_t uProtocol)
    12891289{
    12901290    ProcessWaitResult_T waitResult = ProcessWaitResult_None;
    12911291
    1292     if (   (fWaitFlags & ProcessWaitForFlag_Terminate)
    1293         || (fWaitFlags & ProcessWaitForFlag_StdIn)
    1294         || (fWaitFlags & ProcessWaitForFlag_StdOut)
    1295         || (fWaitFlags & ProcessWaitForFlag_StdErr))
    1296     {
    1297         switch (procStatus)
    1298         {
    1299             case ProcessStatus_TerminatedNormally:
    1300             case ProcessStatus_TerminatedSignal:
    1301             case ProcessStatus_TerminatedAbnormally:
    1302             case ProcessStatus_Down:
    1303                 waitResult = ProcessWaitResult_Terminate;
    1304                 break;
    1305 
    1306             case ProcessStatus_TimedOutKilled:
    1307             case ProcessStatus_TimedOutAbnormally:
    1308                 waitResult = ProcessWaitResult_Timeout;
    1309                 break;
    1310 
    1311             case ProcessStatus_Error:
    1312                 /* Handled above. */
    1313                 break;
    1314 
    1315             case ProcessStatus_Started:
     1292    switch (newStatus)
     1293    {
     1294        case ProcessStatus_TerminatedNormally:
     1295        case ProcessStatus_TerminatedSignal:
     1296        case ProcessStatus_TerminatedAbnormally:
     1297            waitResult = ProcessWaitResult_Terminate;
     1298            break;
     1299        case ProcessStatus_Down:
     1300            waitResult = ProcessWaitResult_Terminate;
     1301            break;
     1302
     1303        case ProcessStatus_TimedOutKilled:
     1304            /* Fall through is intentional. */
     1305        case ProcessStatus_TimedOutAbnormally:
     1306            waitResult = ProcessWaitResult_Timeout;
     1307            break;
     1308
     1309        case ProcessStatus_Error:
     1310            waitResult = ProcessWaitResult_Error;
     1311            break;
     1312
     1313        case ProcessStatus_Started:
     1314        {
     1315            switch (oldStatus)
    13161316            {
    1317                 /*
    1318                  * If ProcessCreateFlag_WaitForProcessStartOnly was specified on process creation the
    1319                  * caller is not interested in getting further process statuses -- so just don't notify
    1320                  * anything here anymore and return.
    1321                  */
    1322                 if (uProcFlags & ProcessCreateFlag_WaitForProcessStartOnly)
    1323                     waitResult = ProcessWaitResult_Start;
    1324                 break;
     1317                case ProcessStatus_Starting:
     1318                    if (fWaitFlags & ProcessWaitForFlag_Start)
     1319                    {
     1320                        waitResult = ProcessWaitResult_Start;
     1321                    }
     1322                    else
     1323                    {
     1324                        /*
     1325                         * If ProcessCreateFlag_WaitForProcessStartOnly was specified on process creation the
     1326                         * caller is not interested in getting further process statuses -- so just don't notify
     1327                         * anything here anymore and return.
     1328                         */
     1329                        if (uProcFlags & ProcessCreateFlag_WaitForProcessStartOnly)
     1330                            waitResult = ProcessWaitResult_Start;
     1331                    }
     1332                    break;
     1333
     1334                default:
     1335                    /* No result available (yet). */
     1336                    break;
    13251337            }
    1326 
    1327             case ProcessStatus_Undefined:
    1328             case ProcessStatus_Starting:
    1329                 /* No result available yet. */
    1330                 break;
    1331 
    1332             default:
    1333                 AssertMsgFailed(("Unhandled process status %ld\n", procStatus));
    1334                 break;
    1335         }
    1336     }
    1337     else if (fWaitFlags & ProcessWaitForFlag_Start)
    1338     {
    1339         switch (procStatus)
    1340         {
    1341             case ProcessStatus_Started:
    1342             case ProcessStatus_Paused:
    1343             case ProcessStatus_Terminating:
    1344             case ProcessStatus_TerminatedNormally:
    1345             case ProcessStatus_TerminatedSignal:
    1346             case ProcessStatus_TerminatedAbnormally:
    1347             case ProcessStatus_Down:
    1348                 waitResult = ProcessWaitResult_Start;
    1349                 break;
    1350 
    1351             case ProcessStatus_Error:
    1352                 waitResult = ProcessWaitResult_Error;
    1353                 break;
    1354 
    1355             case ProcessStatus_TimedOutKilled:
    1356             case ProcessStatus_TimedOutAbnormally:
    1357                 waitResult = ProcessWaitResult_Timeout;
    1358                 break;
    1359 
    1360             case ProcessStatus_Undefined:
    1361             case ProcessStatus_Starting:
    1362                 /* No result available yet. */
    1363                 break;
    1364 
    1365             default:
    1366                 AssertMsgFailed(("Unhandled process status %ld\n", procStatus));
    1367                 break;
    1368         }
    1369     }
    1370 
    1371     /* Filter out waits which are *not* supported using
    1372      * older guest control Guest Additions.
    1373      *
    1374      ** @todo ProcessWaitForFlag_Std* flags are not implemented yet.
    1375      */
    1376     if (uProtocol < 99) /* See @todo above. */
    1377     {
    1378         if (   waitResult == ProcessWaitResult_None
    1379             /* We don't support waiting for stdin, out + err,
    1380              * just skip waiting then. */
    1381             && (   (fWaitFlags & ProcessWaitForFlag_StdIn)
    1382                 || (fWaitFlags & ProcessWaitForFlag_StdOut)
    1383                 || (fWaitFlags & ProcessWaitForFlag_StdErr)
     1338            break;
     1339        }
     1340
     1341        case ProcessStatus_Undefined:
     1342        case ProcessStatus_Starting:
     1343            /* No result available yet. */
     1344            break;
     1345
     1346        default:
     1347            AssertMsgFailed(("Unhandled process status %ld\n", newStatus));
     1348            break;
     1349    }
     1350
     1351    if (newStatus == ProcessStatus_Started)
     1352    {
     1353        /* Filter out waits which are *not* supported using
     1354         * older guest control Guest Additions.
     1355         *
     1356         ** @todo ProcessWaitForFlag_Std* flags are not implemented yet.
     1357         */
     1358        if (uProtocol < 99) /* See @todo above. */
     1359        {
     1360            if (   waitResult == ProcessWaitResult_None
     1361                /* We don't support waiting for stdin, out + err,
     1362                 * just skip waiting then. */
     1363                && (   (fWaitFlags & ProcessWaitForFlag_StdIn)
     1364                    || (fWaitFlags & ProcessWaitForFlag_StdOut)
     1365                    || (fWaitFlags & ProcessWaitForFlag_StdErr)
     1366                   )
    13841367               )
    1385            )
    1386         {
    1387             /* Use _WaitFlagNotSupported because we don't know what to tell the caller. */
    1388             waitResult = ProcessWaitResult_WaitFlagNotSupported;
    1389         }
    1390     }
    1391 
     1368            {
     1369                /* Use _WaitFlagNotSupported because we don't know what to tell the caller. */
     1370                waitResult = ProcessWaitResult_WaitFlagNotSupported;
     1371            }
     1372        }
     1373    }
     1374
     1375#ifdef DEBUG
     1376    LogFlowFunc(("oldStatus=%ld, newStatus=%ld, fWaitFlags=0x%x, waitResult=%ld\n",
     1377                 oldStatus, newStatus, fWaitFlags, waitResult));
     1378#endif
    13921379    return waitResult;
    13931380}
     
    13961383{
    13971384    AssertPtr(mSession);
    1398     return GuestProcess::waitFlagsToResultEx(fWaitFlags, mData.mStatus, mData.mProcess.mFlags,
    1399                                              mSession->getProtocolVersion());
    1400 }
    1401 
    1402 int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc)
     1385    return GuestProcess::waitFlagsToResultEx(fWaitFlags,
     1386                                             mData.mStatus /* curStatus */, mData.mStatus /* newStatus */,
     1387                                             mData.mProcess.mFlags, mSession->getProtocolVersion());
     1388}
     1389
     1390int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS,
     1391                          ProcessWaitResult_T &waitResult, int *pGuestRc)
    14031392{
    14041393    AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER);
    14051394
    1406     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1395    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    14071396
    14081397    LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, procStatus=%RU32, procRc=%Rrc, pGuestRc=%p\n",
     
    14101399
    14111400    /* Did some error occur before? Then skip waiting and return. */
    1412     if (mData.mStatus == ProcessStatus_Error)
     1401    ProcessStatus_T curStatus = mData.mStatus;
     1402    if (curStatus == ProcessStatus_Error)
    14131403    {
    14141404        waitResult = ProcessWaitResult_Error;
     
    14201410
    14211411    waitResult = waitFlagsToResult(fWaitFlags);
    1422     LogFlowThisFunc(("waitFlagToResult=%ld\n", waitResult));
    14231412
    14241413    /* No waiting needed? Return immediately using the last set error. */
     
    14351424
    14361425    GuestWaitEvent *pEvent = NULL;
    1437     std::list < VBoxEventType_T > eventTypes;
     1426    GuestEventTypes eventTypes;
    14381427    try
    14391428    {
     
    14531442     * Do the actual waiting.
    14541443     */
    1455     ProcessStatus_T processStatus = ProcessStatus_Undefined;
     1444    ProcessStatus_T newStatus = ProcessStatus_Undefined;
    14561445    uint64_t u64StartMS = RTTimeMilliTS();
    14571446    for (;;)
     
    14681457                                    uTimeoutMS == RT_INDEFINITE_WAIT
    14691458                                  ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS,
    1470                                   &processStatus, pGuestRc);
     1459                                  &newStatus, pGuestRc);
    14711460        if (RT_SUCCESS(vrc))
    14721461        {
    14731462            alock.acquire();
    14741463
    1475             waitResult = waitFlagsToResultEx(fWaitFlags, processStatus,
     1464            waitResult = waitFlagsToResultEx(fWaitFlags, curStatus, newStatus,
    14761465                                             mData.mProcess.mFlags, mSession->getProtocolVersion());
    1477             LogFlowThisFunc(("Got new status change: waitResult=%ld, processStatus=%ld\n",
    1478                              waitResult, processStatus));
     1466#ifdef DEBUG
     1467            LogFlowThisFunc(("Got new status change: fWaitFlags=0x%x, newStatus=%ld, waitResult=%ld\n",
     1468                             fWaitFlags, newStatus, waitResult));
     1469#endif
    14791470            if (ProcessWaitResult_None != waitResult) /* We got a waiting result. */
    14801471                break;
     
    14881479    unregisterWaitEvent(pEvent);
    14891480
    1490     LogFlowThisFunc(("Returned waitResult=%ld, processStatus=%ld, rc=%Rrc\n",
    1491                      waitResult, processStatus, vrc));
     1481    LogFlowThisFunc(("Returned waitResult=%ld, newStatus=%ld, rc=%Rrc\n",
     1482                     waitResult, newStatus, vrc));
    14921483    return vrc;
    14931484}
     
    15011492    ComPtr<IEvent> pIEvent;
    15021493    int vrc = waitForEvent(pEvent, uTimeoutMS,
    1503                            &evtType, pIEvent.asOutParam());
     1494                                 &evtType, pIEvent.asOutParam());
    15041495    if (RT_SUCCESS(vrc))
    15051496    {
     
    15471538    {
    15481539        vrc = waitForEvent(pEvent, uTimeoutMS,
    1549                            &evtType, pIEvent.asOutParam());
     1540                                 &evtType, pIEvent.asOutParam());
    15501541        if (RT_SUCCESS(vrc))
    15511542        {
    1552 #ifdef DEBUG_andy
    1553             LogFlowThisFunc(("pEvent=%p, evtType=%ld\n", pEvent, evtType));
    1554 #endif
    15551543            if (evtType == VBoxEventType_OnGuestProcessOutput)
    15561544            {
     
    15601548                ULONG uHandleEvent;
    15611549                HRESULT hr = pProcessEvent->COMGETTER(Handle)(&uHandleEvent);
    1562                 LogFlowThisFunc(("Received output, uHandle=%RU32\n", uHandleEvent));
    15631550                if (   SUCCEEDED(hr)
    15641551                    && uHandleEvent == uHandle)
     
    15791566                            else
    15801567                                vrc = VERR_BUFFER_OVERFLOW;
     1568
     1569                            LogFlowThisFunc(("Read %zu bytes (uHandle=%RU32), rc=%Rrc\n",
     1570                                             cbRead, uHandleEvent, vrc));
    15811571                        }
    15821572                    }
     
    16081598    }
    16091599
    1610     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1600    LogFlowFuncLeaveRC(vrc);
    16111601    return vrc;
    16121602}
     
    16291619        Assert(!pProcessEvent.isNull());
    16301620
    1631         HRESULT hr;
     1621        ProcessStatus_T procStatus;
     1622        HRESULT hr = pProcessEvent->COMGETTER(Status)(&procStatus);
     1623        ComAssertComRC(hr);
    16321624        if (pProcessStatus)
    1633         {
    1634             hr = pProcessEvent->COMGETTER(Status)(pProcessStatus);
    1635             ComAssertComRC(hr);
    1636         }
     1625            *pProcessStatus = procStatus;
    16371626
    16381627        ComPtr<IVirtualBoxErrorInfo> errorInfo;
     
    16441633        ComAssertComRC(hr);
    16451634
    1646         LogFlowThisFunc(("resultDetail=%RI32 (rc=%Rrc)\n",
    1647                          lGuestRc, lGuestRc));
     1635        LogFlowThisFunc(("procStatus=%RU32, resultDetail=%RI32 (rc=%Rrc)\n",
     1636                         procStatus, lGuestRc, lGuestRc));
    16481637
    16491638        if (RT_FAILURE((int)lGuestRc))
     
    16541643    }
    16551644
    1656     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1645    LogFlowFuncLeaveRC(vrc);
    16571646    return vrc;
    16581647}
     
    17101699
    17111700    GuestWaitEvent *pEvent = NULL;
    1712     std::list < VBoxEventType_T > eventTypes;
     1701    GuestEventTypes eventTypes;
    17131702    try
    17141703    {
     
    18141803    LogFlowThisFunc(("rc=%Rrc, cbRead=%RU32\n", vrc, cbRead));
    18151804
    1816     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1805    LogFlowFuncLeaveRC(vrc);
    18171806    return hr;
    18181807#endif /* VBOX_WITH_GUEST_CONTROL */
     
    18611850    mSession->processRemoveFromList(this);
    18621851
    1863     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1852    LogFlowFuncLeaveRC(vrc);
    18641853    return hr;
    18651854#endif /* VBOX_WITH_GUEST_CONTROL */
     
    19091898    }
    19101899
    1911     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1900    LogFlowFuncLeaveRC(vrc);
    19121901    return hr;
    19131902#endif /* VBOX_WITH_GUEST_CONTROL */
     
    19781967    *aWritten = (ULONG)cbWritten;
    19791968
    1980     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     1969    LogFlowFuncLeaveRC(vrc);
    19811970    return hr;
    19821971#endif /* VBOX_WITH_GUEST_CONTROL */
     
    20292018    AssertPtrReturn(pGuestSession, VERR_INVALID_POINTER);
    20302019
    2031     pSession     = pGuestSession;
     2020    pSession = pGuestSession;
    20322021    mStartupInfo = startupInfo;
    20332022
     
    20502039    }
    20512040
    2052     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     2041    LogFlowFuncLeaveRC(vrc);
    20532042    return vrc;
    20542043}
     
    20972086}
    20982087
     2088/* static */
     2089int GuestProcessTool::Run(      GuestSession            *pGuestSession,
     2090                          const GuestProcessStartupInfo &startupInfo,
     2091                                int                     *pGuestRc)
     2092{
     2093    return RunEx(pGuestSession, startupInfo,
     2094                 NULL /* pStrmOutObjects */, 0 /* cStrmOutObjects */,
     2095                 pGuestRc);
     2096}
     2097
     2098/* static */
     2099int GuestProcessTool::RunEx(      GuestSession            *pGuestSession,
     2100                            const GuestProcessStartupInfo &startupInfo,
     2101                                  GuestCtrlStreamObjects  *pStrmOutObjects,
     2102                                  uint32_t                 cStrmOutObjects,
     2103                                  int                     *pGuestRc)
     2104{
     2105    GuestProcessTool procTool; int guestRc;
     2106    int vrc = procTool.Init(pGuestSession, startupInfo, false /* Async */, &guestRc);
     2107    if (RT_SUCCESS(vrc))
     2108    {
     2109        while (cStrmOutObjects--)
     2110        {
     2111            try
     2112            {
     2113                GuestProcessStreamBlock strmBlk;
     2114                vrc = procTool.WaitEx(  pStrmOutObjects
     2115                                      ? GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK
     2116                                      : GUESTPROCESSTOOL_FLAG_NONE, &strmBlk, &guestRc);
     2117                if (pStrmOutObjects)
     2118                    pStrmOutObjects->push_back(strmBlk);
     2119            }
     2120            catch (std::bad_alloc)
     2121            {
     2122                vrc = VERR_NO_MEMORY;
     2123            }
     2124        }
     2125    }
     2126
     2127    if (RT_SUCCESS(vrc))
     2128    {
     2129        /* Make sure the process runs until completion. */
     2130        vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
     2131
     2132        Assert(RT_SUCCESS(guestRc));
     2133        guestRc = procTool.TerminatedOk(NULL /* Exit code */);
     2134        if (pGuestRc)
     2135            *pGuestRc = guestRc;
     2136    }
     2137    else if (vrc == VERR_GSTCTL_GUEST_ERROR)
     2138    {
     2139        if (pGuestRc)
     2140            *pGuestRc = guestRc;
     2141    }
     2142
     2143    LogFlowFunc(("Returned rc=%Rrc, guestRc=%Rrc\n", vrc, guestRc));
     2144    return vrc;
     2145}
     2146
    20992147int GuestProcessTool::TerminatedOk(LONG *pExitCode)
    21002148{
     
    21022150    /* pExitCode is optional. */
    21032151
     2152    int vrc;
    21042153    if (!IsRunning())
    21052154    {
     
    21112160            *pExitCode = exitCode;
    21122161
    2113         if (exitCode != 0)
    2114             return VERR_NOT_EQUAL; /** @todo Special guest control rc needed! */
    2115         return VINF_SUCCESS;
    2116     }
    2117 
    2118     return VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
     2162        vrc = (exitCode != 0)
     2163              /** @todo Special guest control rc needed! */
     2164            ? VERR_NOT_EQUAL : VINF_SUCCESS;
     2165    }
     2166    else
     2167        vrc = VERR_INVALID_STATE; /** @todo Special guest control rc needed! */
     2168
     2169    LogFlowFuncLeaveRC(vrc);
     2170    return vrc;
    21192171}
    21202172
    21212173int GuestProcessTool::Wait(uint32_t fFlags, int *pGuestRc)
    21222174{
    2123     return WaitEx(fFlags, NULL /* pStreamBlock */, pGuestRc);
    2124 }
    2125 
    2126 int GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStreamBlock, int *pGuestRc)
    2127 {
    2128     LogFlowThisFunc(("pSession=%p, fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n",
    2129                      pSession, fFlags, pStreamBlock, pGuestRc));
    2130 
    2131     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    2132     Assert(!pProcess.isNull());
    2133     /* Other parameters are optional. */
     2175    return WaitEx(fFlags, NULL /* pStrmBlkOut */, pGuestRc);
     2176}
     2177
     2178int GuestProcessTool::WaitEx(uint32_t fFlags, GuestProcessStreamBlock *pStrmBlkOut, int *pGuestRc)
     2179{
     2180    LogFlowThisFunc(("fFlags=0x%x, pStreamBlock=%p, pGuestRc=%p\n",
     2181                     fFlags, pStrmBlkOut, pGuestRc));
    21342182
    21352183    /* Can we parse the next block without waiting? */
     
    21372185    if (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK)
    21382186    {
    2139         AssertPtr(pStreamBlock);
    2140         vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock);
     2187        AssertPtr(pStrmBlkOut);
     2188        vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStrmBlkOut);
    21412189        if (RT_SUCCESS(vrc))
    21422190            return vrc;
     
    21512199        fWaitFlags |= ProcessWaitForFlag_StdErr;
    21522200
    2153     LogFlowThisFunc(("waitFlags=0x%x\n", fWaitFlags));
    2154 
    21552201    /** @todo Decrease timeout while running. */
     2202    uint64_t u64StartMS = RTTimeMilliTS();
    21562203    uint32_t uTimeoutMS = mStartupInfo.mTimeoutMS;
    21572204
     
    21652212    bool fHandleStdErr = false;
    21662213
     2214    /**
     2215     * Updates the elapsed time and checks if a
     2216     * timeout happened, then breaking out of the loop.
     2217     */
     2218#define UPDATE_AND_CHECK_ELAPSED_TIME()          \
     2219    u64ElapsedMS = RTTimeMilliTS() - u64StartMS; \
     2220    if (   uTimeoutMS   != RT_INDEFINITE_WAIT    \
     2221        && u64ElapsedMS >= uTimeoutMS)           \
     2222    {                                            \
     2223        vrc = VERR_TIMEOUT;                      \
     2224        break;                                   \
     2225    }
     2226
     2227    /**
     2228     * Returns the remaining time (in ms).
     2229     */
     2230#define GET_REMAINING_TIME                                     \
     2231      uTimeoutMS == RT_INDEFINITE_WAIT                         \
     2232    ? RT_INDEFINITE_WAIT : uTimeoutMS - (uint32_t)u64ElapsedMS \
     2233
    21672234    ProcessWaitResult_T waitRes;
    21682235    do
    21692236    {
    2170         vrc = pProcess->waitFor(fWaitFlags,
    2171                                 uTimeoutMS, waitRes, &guestRc);
     2237        uint64_t u64ElapsedMS;
     2238        UPDATE_AND_CHECK_ELAPSED_TIME();
     2239
     2240        vrc = pProcess->waitFor(fWaitFlags, GET_REMAINING_TIME,
     2241                                waitRes, &guestRc);
    21722242        if (RT_FAILURE(vrc))
    21732243            break;
     
    22192289        }
    22202290
     2291        if (RT_FAILURE(vrc))
     2292            break;
     2293
    22212294        if (fHandleStdOut)
    22222295        {
     2296            UPDATE_AND_CHECK_ELAPSED_TIME();
     2297
    22232298            cbRead = 0;
    22242299            vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
    2225                                      uTimeoutMS, byBuf, sizeof(byBuf),
     2300                                     GET_REMAINING_TIME,
     2301                                     byBuf, sizeof(byBuf),
    22262302                                     &cbRead, &guestRc);
    2227             if (RT_FAILURE(vrc))
     2303            if (   RT_FAILURE(vrc)
     2304                || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)
    22282305                break;
    22292306
     
    22362313                    && (fFlags & GUESTPROCESSTOOL_FLAG_STDOUT_BLOCK))
    22372314                {
    2238                     AssertPtr(pStreamBlock);
    2239                     vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStreamBlock);
     2315                    AssertPtr(pStrmBlkOut);
     2316                    vrc = GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, *pStrmBlkOut);
     2317
     2318                    /* When successful, break out of the loop because we're done
     2319                     * with reading the first stream block. */
    22402320                    if (RT_SUCCESS(vrc))
    22412321                        fDone = true;
     
    22482328        if (fHandleStdErr)
    22492329        {
     2330            UPDATE_AND_CHECK_ELAPSED_TIME();
     2331
    22502332            cbRead = 0;
    22512333            vrc = pProcess->readData(OUTPUT_HANDLE_ID_STDERR, sizeof(byBuf),
    2252                                      uTimeoutMS, byBuf, sizeof(byBuf),
     2334                                     GET_REMAINING_TIME,
     2335                                     byBuf, sizeof(byBuf),
    22532336                                     &cbRead, &guestRc);
    2254             if (RT_FAILURE(vrc))
     2337            if (   RT_FAILURE(vrc)
     2338                || vrc == VWRN_GSTCTL_OBJECTSTATE_CHANGED)
    22552339                break;
    22562340
     
    22662350    } while (!fDone && RT_SUCCESS(vrc));
    22672351
     2352#undef UPDATE_AND_CHECK_ELAPSED_TIME
     2353#undef GET_REMAINING_TIME
     2354
    22682355    LogFlowThisFunc(("Loop ended with rc=%Rrc, guestRc=%Rrc, waitRes=%ld\n",
    22692356                     vrc, guestRc, waitRes));
     
    22712358        *pGuestRc = guestRc;
    22722359
    2273     LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
     2360    LogFlowFuncLeaveRC(vrc);
    22742361    return vrc;
    22752362}
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r48342 r49349  
    114114            {
    115115                Assert(!mSession.isNull());
    116                 int rc2 = mSession->signalWaitEvents(aType, aEvent);
     116                int rc2 = mSession->signalWaitEvent(aType, aEvent);
    117117#ifdef DEBUG_andy
    118118                LogFlowFunc(("Signalling events of type=%ld, session=%p resulted in rc=%Rrc\n",
     
    289289         itDirs != mData.mDirectories.end(); ++itDirs)
    290290    {
    291         (*itDirs)->Release();
     291        itDirs->second->Release();
    292292    }
    293293    mData.mDirectories.clear();
     
    665665
    666666    GuestWaitEvent *pEvent = NULL;
    667     std::list < VBoxEventType_T > eventTypes;
     667    GuestEventTypes eventTypes;
    668668    try
    669669    {
     
    702702}
    703703
     704int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode,
     705                                          uint32_t uFlags, int *pGuestRc)
     706{
     707    LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
     708                     strPath.c_str(), uMode, uFlags));
     709
     710    int vrc = VINF_SUCCESS;
     711
     712    GuestProcessStartupInfo procInfo;
     713    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
     714    procInfo.mFlags   = ProcessCreateFlag_Hidden;
     715
     716    try
     717    {
     718        /* Construct arguments. */
     719        if (uFlags & DirectoryCreateFlag_Parents)
     720            procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
     721        if (uMode)
     722        {
     723            procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
     724
     725            char szMode[16];
     726            if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
     727            {
     728                procInfo.mArguments.push_back(Utf8Str(szMode));
     729            }
     730            else
     731                vrc = VERR_BUFFER_OVERFLOW;
     732        }
     733        procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
     734    }
     735    catch (std::bad_alloc)
     736    {
     737        vrc = VERR_NO_MEMORY;
     738    }
     739
     740    if (RT_SUCCESS(vrc))
     741        vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
     742
     743    LogFlowFuncLeaveRC(vrc);
     744    return vrc;
     745}
     746
     747inline bool GuestSession::directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir)
     748{
     749    SessionDirectories::const_iterator it = mData.mDirectories.find(uDirID);
     750    if (it != mData.mDirectories.end())
     751    {
     752        if (pDir)
     753            *pDir = it->second;
     754        return true;
     755    }
     756    return false;
     757}
     758
     759int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
     760{
     761    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
     762
     763    int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
     764    if (RT_SUCCESS(vrc))
     765    {
     766        vrc = objData.mType == FsObjType_Directory
     767            ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
     768    }
     769
     770    LogFlowFuncLeaveRC(vrc);
     771    return vrc;
     772}
     773
    704774int GuestSession::directoryRemoveFromList(GuestDirectory *pDirectory)
    705775{
     
    709779         itDirs != mData.mDirectories.end(); ++itDirs)
    710780    {
    711         if (pDirectory == (*itDirs))
     781        if (pDirectory == itDirs->second)
    712782        {
    713783            Bstr strName;
    714             HRESULT hr = (*itDirs)->COMGETTER(DirectoryName)(strName.asOutParam());
     784            HRESULT hr = itDirs->second->COMGETTER(DirectoryName)(strName.asOutParam());
    715785            ComAssertComRC(hr);
    716786
     
    727797}
    728798
    729 int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc)
    730 {
    731     /* pGuestRc is optional. */
    732 
    733     LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
    734                      strPath.c_str(), uMode, uFlags));
    735 
    736     GuestProcessStartupInfo procInfo;
    737     procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
    738     procInfo.mFlags   = ProcessCreateFlag_Hidden;
    739 
    740     int vrc = VINF_SUCCESS;
    741 
    742     /* Construct arguments. */
    743     if (uFlags & DirectoryCreateFlag_Parents)
    744         procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
    745     if (uMode)
    746     {
    747         procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
    748 
    749         char szMode[16];
    750         if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
    751         {
    752             procInfo.mArguments.push_back(Utf8Str(szMode));
    753         }
    754         else
    755             vrc = VERR_BUFFER_OVERFLOW;
    756     }
    757     procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
    758 
     799int GuestSession::directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFlags,
     800                                          int *pGuestRc)
     801{
     802    AssertReturn(!(uFlags & ~DIRREMOVE_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
     803
     804    LogFlowThisFunc(("strPath=%s, uFlags=0x%x\n", strPath.c_str(), uFlags));
     805
     806    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     807
     808    GuestWaitEvent *pEvent = NULL;
     809    int vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
     810                                &pEvent);
     811    if (RT_FAILURE(vrc))
     812        return vrc;
     813
     814    /* Prepare HGCM call. */
     815    VBOXHGCMSVCPARM paParms[8];
     816    int i = 0;
     817    paParms[i++].setUInt32(pEvent->ContextID());
     818    paParms[i++].setPointer((void*)strPath.c_str(),
     819                            (ULONG)strPath.length() + 1);
     820    paParms[i++].setUInt32(uFlags);
     821
     822    alock.release(); /* Drop write lock before sending. */
     823
     824    vrc = sendCommand(HOST_DIR_REMOVE, i, paParms);
    759825    if (RT_SUCCESS(vrc))
    760826    {
    761         int guestRc;
    762         GuestProcessTool procTool;
    763         vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
    764         if (RT_SUCCESS(vrc))
    765         {
    766             if (RT_SUCCESS(guestRc))
    767                 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    768         }
    769 
    770         if (RT_SUCCESS(vrc))
    771         {
    772             if (RT_SUCCESS(guestRc))
    773                 guestRc = procTool.TerminatedOk(NULL /* Exit code */);
    774         }
    775 
     827        vrc = pEvent->Wait(30 * 1000);
    776828        if (   vrc == VERR_GSTCTL_GUEST_ERROR
    777829            && pGuestRc)
    778         {
    779             *pGuestRc = guestRc;
    780         }
    781     }
     830            *pGuestRc = pEvent->GuestResult();
     831    }
     832
     833    unregisterWaitEvent(pEvent);
    782834
    783835    LogFlowFuncLeaveRC(vrc);
     
    785837}
    786838
    787 int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
    788 {
    789     LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
    790 
    791     int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
    792     if (RT_SUCCESS(vrc))
    793     {
    794         vrc = objData.mType == FsObjType_Directory
    795             ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
    796     }
    797 
    798     LogFlowFuncLeaveRC(vrc);
    799     return vrc;
    800 }
    801 
    802839int GuestSession::objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath,
    803840                                           bool fDirectory, const Utf8Str &strName, int *pGuestRc)
    804841{
     842    LogFlowThisFunc(("strTemplate=%s, strPath=%s, fDirectory=%RTbool, strName=%s\n",
     843                     strTemplate.c_str(), strPath.c_str(), fDirectory, strName.c_str()));
     844
     845    int vrc = VINF_SUCCESS;
     846
    805847    GuestProcessStartupInfo procInfo;
    806848    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKTEMP);
    807849    procInfo.mFlags   = ProcessCreateFlag_WaitForStdOut;
    808     procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    809     if (fDirectory)
    810         procInfo.mArguments.push_back(Utf8Str("-d"));
    811     if (strPath.length()) /* Otherwise use /tmp or equivalent. */
    812     {
    813         procInfo.mArguments.push_back(Utf8Str("-t"));
    814         procInfo.mArguments.push_back(strPath);
    815     }
    816     procInfo.mArguments.push_back(strTemplate);
    817 
    818     GuestProcessTool procTool; int guestRc;
    819     int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
     850
     851    try
     852    {
     853        procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     854        if (fDirectory)
     855            procInfo.mArguments.push_back(Utf8Str("-d"));
     856        if (strPath.length()) /* Otherwise use /tmp or equivalent. */
     857        {
     858            procInfo.mArguments.push_back(Utf8Str("-t"));
     859            procInfo.mArguments.push_back(strPath);
     860        }
     861        procInfo.mArguments.push_back(strTemplate);
     862    }
     863    catch (std::bad_alloc)
     864    {
     865        vrc = VERR_NO_MEMORY;
     866    }
     867
    820868    if (RT_SUCCESS(vrc))
    821     {
    822         if (RT_SUCCESS(guestRc))
    823             vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    824     }
    825 
    826     if (RT_SUCCESS(vrc))
    827     {
    828         if (RT_SUCCESS(guestRc))
    829             guestRc = procTool.TerminatedOk(NULL /* Exit code */);
    830     }
    831 
    832     if (   vrc == VERR_GSTCTL_GUEST_ERROR
    833         && pGuestRc)
    834     {
    835         *pGuestRc = guestRc;
    836     }
     869        vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
    837870
    838871    LogFlowFuncLeaveRC(vrc);
     
    840873}
    841874
    842 int GuestSession::directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter,
    843                                         uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory)
     875int GuestSession::directoryOpenInternal(const GuestDirectoryOpenInfo &openInfo,
     876                                        ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc)
    844877{
    845878    LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
    846                      strPath.c_str(), strFilter.c_str(), uFlags));
     879                     openInfo.mPath.c_str(), openInfo.mFilter.c_str(), openInfo.mFlags));
    847880
    848881    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     882
     883    int rc = VERR_MAX_PROCS_REACHED;
     884    if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS)
     885        return rc;
     886
     887    /* Create a new (host-based) directory ID and assign it. */
     888    uint32_t uNewDirID = 0;
     889    ULONG uTries = 0;
     890
     891    for (;;)
     892    {
     893        /* Is the directory ID already used? */
     894        if (!directoryExists(uNewDirID, NULL /* pDirectory */))
     895        {
     896            /* Callback with context ID was not found. This means
     897             * we can use this context ID for our new callback we want
     898             * to add below. */
     899            rc = VINF_SUCCESS;
     900            break;
     901        }
     902        uNewDirID++;
     903        if (uNewDirID == VBOX_GUESTCTRL_MAX_OBJECTS)
     904            uNewDirID = 0;
     905
     906        if (++uTries == UINT32_MAX)
     907            break; /* Don't try too hard. */
     908    }
     909
     910    if (RT_FAILURE(rc))
     911        return rc;
    849912
    850913    /* Create the directory object. */
     
    853916        return VERR_COM_UNEXPECTED;
    854917
    855     int vrc = pDirectory->init(this /* Parent */,
    856                                strPath, strFilter, uFlags);
     918    Console *pConsole = mParent->getConsole();
     919    AssertPtr(pConsole);
     920
     921    int vrc = pDirectory->init(pConsole, this /* Parent */,
     922                               uNewDirID, openInfo);
    857923    if (RT_FAILURE(vrc))
    858924        return vrc;
    859925
    860     /* Add the created directory to our vector. */
    861     mData.mDirectories.push_back(pDirectory);
    862 
    863     LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
    864                  strPath.c_str(), mData.mSession.mID));
     926    /*
     927     * Since this is a synchronous guest call we have to
     928     * register the file object first, releasing the session's
     929     * lock and then proceed with the actual opening command
     930     * -- otherwise the file's opening callback would hang
     931     * because the session's lock still is in place.
     932     */
     933    try
     934    {
     935        /* Add the created directory to our map. */
     936        mData.mDirectories[uNewDirID] = pDirectory;
     937        mData.mNumObjects++;
     938        Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
     939
     940        LogFlowFunc(("Added new guest directory \"%s\" (Session: %RU32) (now total %ld dirs, %ld objects)\n",
     941                     openInfo.mPath.c_str(), mData.mSession.mID, mData.mFiles.size(), mData.mNumObjects));
     942
     943        alock.release(); /* Release lock before firing off event. */
     944
     945        /** @todo Fire off a VBoxEventType_OnGuestDirectoryRegistered event? */
     946    }
     947    catch (std::bad_alloc &)
     948    {
     949        rc = VERR_NO_MEMORY;
     950    }
     951
     952    if (RT_SUCCESS(rc))
     953    {
     954        /* Nothing further to do here yet. */
     955        if (pGuestRc)
     956            *pGuestRc = VINF_SUCCESS;
     957    }
    865958
    866959    LogFlowFuncLeaveRC(vrc);
    867960    return vrc;
     961}
     962
     963int GuestSession::dispatchToDirectory(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
     964{
     965    LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
     966
     967    AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER);
     968    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     969
     970    if (pSvcCb->mParms < 3)
     971        return VERR_INVALID_PARAMETER;
     972
     973    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     974
     975    uint32_t uDirID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID);
     976#ifdef DEBUG
     977    LogFlowFunc(("uDirID=%RU32 (%RU32 total)\n",
     978                 uDirID, mData.mFiles.size()));
     979#endif
     980    int rc;
     981    SessionDirectories::const_iterator itDir
     982        = mData.mDirectories.find(uDirID);
     983    if (itDir != mData.mDirectories.end())
     984    {
     985        ComObjPtr<GuestDirectory> pDirectory(itDir->second);
     986        Assert(!pDirectory.isNull());
     987
     988        alock.release();
     989
     990        rc = pDirectory->callbackDispatcher(pCtxCb, pSvcCb);
     991    }
     992    else
     993        rc = VERR_NOT_FOUND;
     994
     995    LogFlowFuncLeaveRC(rc);
     996    return rc;
    868997}
    869998
     
    9011030}
    9021031
     1032int GuestSession::dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
     1033{
     1034    LogFlowFunc(("pCtxCb=%p, pSvcCb=%p\n", pCtxCb, pSvcCb));
     1035
     1036    AssertPtrReturn(pCtxCb, VERR_INVALID_POINTER);
     1037    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
     1038
     1039    int rc;
     1040    uint32_t uObjectID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCtxCb->uContextID);
     1041
     1042    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1043
     1044    /* Since we don't know which type the object is, we need to through all
     1045     * all objects. */
     1046    /** @todo Speed this up by adding an object type to the callback context! */
     1047    SessionProcesses::const_iterator itProc = mData.mProcesses.find(uObjectID);
     1048    if (itProc == mData.mProcesses.end())
     1049    {
     1050        SessionFiles::const_iterator itFile = mData.mFiles.find(uObjectID);
     1051        if (itFile != mData.mFiles.end())
     1052        {
     1053            alock.release();
     1054
     1055            rc = dispatchToFile(pCtxCb, pSvcCb);
     1056        }
     1057        else
     1058        {
     1059            SessionDirectories::const_iterator itDir = mData.mDirectories.find(uObjectID);
     1060            if (itDir != mData.mDirectories.end())
     1061            {
     1062                alock.release();
     1063
     1064                rc = dispatchToDirectory(pCtxCb, pSvcCb);
     1065            }
     1066            else
     1067                rc = VERR_NOT_FOUND;
     1068        }
     1069    }
     1070    else
     1071    {
     1072        alock.release();
     1073
     1074        rc = dispatchToProcess(pCtxCb, pSvcCb);
     1075    }
     1076
     1077    LogFlowFuncLeaveRC(rc);
     1078    return rc;
     1079}
     1080
    9031081int GuestSession::dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
    9041082{
     
    9491127#endif
    9501128
    951     int rc = VINF_SUCCESS;
     1129    int rc;
    9521130    switch (pCbCtx->uFunction)
    9531131    {
     
    9561134            break;
    9571135
    958         case GUEST_SESSION_NOTIFY:
     1136        case GUEST_SESSION_NOTIFY: /* Guest Additions >= 4.3.0. */
    9591137        {
    9601138            rc = onSessionStatusChange(pCbCtx, pSvcCb);
     
    10241202int GuestSession::fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc)
    10251203{
     1204    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
     1205
     1206    int vrc = VINF_SUCCESS;
     1207
    10261208    GuestProcessStartupInfo procInfo;
    10271209    GuestProcessStream      streamOut;
     
    10291211    procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_RM);
    10301212    procInfo.mFlags   = ProcessCreateFlag_WaitForStdOut;
    1031     procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    1032     procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
    1033 
    1034     GuestProcessTool procTool; int guestRc;
    1035     int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
     1213
     1214    try
     1215    {
     1216        procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     1217        procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
     1218    }
     1219    catch (std::bad_alloc)
     1220    {
     1221        vrc = VERR_NO_MEMORY;
     1222    }
     1223
    10361224    if (RT_SUCCESS(vrc))
    1037         vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    1038 
    1039     if (RT_SUCCESS(vrc))
    1040     {
    1041         if (RT_SUCCESS(guestRc))
    1042             guestRc = procTool.TerminatedOk(NULL /* Exit code */);
    1043     }
    1044 
    1045     if (   vrc == VERR_GSTCTL_GUEST_ERROR
    1046         && pGuestRc)
    1047     {
    1048         *pGuestRc = guestRc;
    1049     }
     1225        vrc = GuestProcessTool::Run(this, procInfo, pGuestRc);
    10501226
    10511227    LogFlowFuncLeaveRC(vrc);
     
    10531229}
    10541230
    1055 int GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo, ComObjPtr<GuestFile> &pFile, int *pGuestRc)
     1231int GuestSession::fileOpenInternal(const GuestFileOpenInfo &openInfo,
     1232                                   ComObjPtr<GuestFile> &pFile, int *pGuestRc)
    10561233{
    10571234    LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, uOffset=%RU64\n",
     
    10801257    {
    10811258        /* Is the file ID already used? */
    1082         if (!fileExists(uNewFileID, NULL /* pProgress */))
     1259        if (!fileExists(uNewFileID, NULL /* pFile */))
    10831260        {
    10841261            /* Callback with context ID was not found. This means
     
    11851362    LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
    11861363
     1364    int vrc = VINF_SUCCESS;
     1365
    11871366    /** @todo Merge this with IGuestFile::queryInfo(). */
    11881367    GuestProcessStartupInfo procInfo;
     
    11901369    procInfo.mFlags   = ProcessCreateFlag_WaitForStdOut;
    11911370
    1192     /* Construct arguments. */
    1193     procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
    1194     procInfo.mArguments.push_back(strPath);
    1195 
    1196     GuestProcessTool procTool; int guestRc;
    1197     int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
     1371    try
     1372    {
     1373        /* Construct arguments. */
     1374        procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
     1375        procInfo.mArguments.push_back(strPath);
     1376    }
     1377    catch (std::bad_alloc)
     1378    {
     1379        vrc = VERR_NO_MEMORY;
     1380    }
     1381
     1382    int guestRc; GuestCtrlStreamObjects stdOut;
    11981383    if (RT_SUCCESS(vrc))
    1199         vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
    1200     if (RT_SUCCESS(vrc))
    1201     {
    1202         guestRc = procTool.TerminatedOk(NULL /* Exit code */);
    1203         if (RT_SUCCESS(guestRc))
    1204         {
    1205             GuestProcessStreamBlock curBlock;
    1206             vrc = procTool.GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT,  curBlock);
    1207             /** @todo Check for more / validate blocks! */
    1208             if (RT_SUCCESS(vrc))
    1209                 vrc = objData.FromStat(curBlock);
    1210         }
    1211     }
    1212 
    1213     if (   vrc == VERR_GSTCTL_GUEST_ERROR
    1214         && pGuestRc)
    1215     {
    1216         *pGuestRc = guestRc;
     1384        vrc = GuestProcessTool::RunEx(this, procInfo,
     1385                                      &stdOut, 1 /* cStrmOutObjects */,
     1386                                      &guestRc);
     1387    if (   RT_SUCCESS(vrc)
     1388        && RT_SUCCESS(guestRc))
     1389    {
     1390        if (!stdOut.empty())
     1391            vrc = objData.FromStat(stdOut.at(0));
     1392        else
     1393            vrc = VERR_NO_DATA;
    12171394    }
    12181395
     
    14031580    /* Set current session status. */
    14041581    mData.mStatus = GuestSessionStatus_Starting;
     1582    mData.mRC = VINF_SUCCESS; /* Clear previous error, if any. */
    14051583
    14061584    int vrc;
    14071585
    14081586    GuestWaitEvent *pEvent = NULL;
    1409     std::list < VBoxEventType_T > eventTypes;
     1587    GuestEventTypes eventTypes;
    14101588    try
    14111589    {
     
    14401618    vrc = sendCommand(HOST_SESSION_CREATE, i, paParms);
    14411619    if (RT_SUCCESS(vrc))
     1620    {
    14421621        vrc = waitForStatusChange(pEvent, GuestSessionWaitForFlag_Start,
    14431622                                  30 * 1000 /* 30s timeout */,
    14441623                                  NULL /* Session status */, pGuestRc);
     1624    }
     1625    else
     1626    {
     1627        /*
     1628         * Unable to start guest session - update its current state.
     1629         * Since there is no (official API) way to recover a failed guest session
     1630         * this also marks the end state. Internally just calling this
     1631         * same function again will work though.
     1632         */
     1633        mData.mStatus = GuestSessionStatus_Error;
     1634        mData.mRC = vrc;
     1635    }
    14451636
    14461637    unregisterWaitEvent(pEvent);
     
    14981689    int vrc = pSession->startSessionInternal(NULL /* Guest rc, ignored */);
    14991690    /* Nothing to do here anymore. */
     1691
     1692    LogFlowFuncLeaveRC(vrc);
     1693    return vrc;
     1694}
     1695
     1696int GuestSession::pathRenameInternal(const Utf8Str &strSource, const Utf8Str &strDest,
     1697                                     uint32_t uFlags, int *pGuestRc)
     1698{
     1699    AssertReturn(!(uFlags & ~PATHRENAME_FLAG_VALID_MASK), VERR_INVALID_PARAMETER);
     1700
     1701    LogFlowThisFunc(("strSource=%s, strDest=%s, uFlags=0x%x\n",
     1702                     strSource.c_str(), strDest.c_str(), uFlags));
     1703
     1704    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1705
     1706    GuestWaitEvent *pEvent = NULL;
     1707    int vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
     1708                                &pEvent);
     1709    if (RT_FAILURE(vrc))
     1710        return vrc;
     1711
     1712    /* Prepare HGCM call. */
     1713    VBOXHGCMSVCPARM paParms[8];
     1714    int i = 0;
     1715    paParms[i++].setUInt32(pEvent->ContextID());
     1716    paParms[i++].setPointer((void*)strSource.c_str(),
     1717                            (ULONG)strSource.length() + 1);
     1718    paParms[i++].setPointer((void*)strDest.c_str(),
     1719                            (ULONG)strDest.length() + 1);
     1720    paParms[i++].setUInt32(uFlags);
     1721
     1722    alock.release(); /* Drop write lock before sending. */
     1723
     1724    vrc = sendCommand(HOST_PATH_RENAME, i, paParms);
     1725    if (RT_SUCCESS(vrc))
     1726    {
     1727        vrc = pEvent->Wait(30 * 1000);
     1728        if (   vrc == VERR_GSTCTL_GUEST_ERROR
     1729            && pGuestRc)
     1730            *pGuestRc = pEvent->GuestResult();
     1731    }
     1732
     1733    unregisterWaitEvent(pEvent);
    15001734
    15011735    LogFlowFuncLeaveRC(vrc);
     
    16251859    {
    16261860        /* Is the context ID already used? */
    1627         if (!processExists(uNewProcessID, NULL /* pProgress */))
     1861        if (!processExists(uNewProcessID, NULL /* pProcess */))
    16281862        {
    16291863            /* Callback with context ID was not found. This means
     
    19882222
    19892223    GuestWaitEvent *pEvent = NULL;
    1990     std::list < VBoxEventType_T > eventTypes;
     2224    GuestEventTypes eventTypes;
    19912225    try
    19922226    {
     
    21102344    /* Remove ourselves from the session list. */
    21112345    int rc2 = mParent->sessionRemove(this);
     2346    if (rc2 == VERR_NOT_FOUND) /* Not finding the session anymore isn't critical. */
     2347        rc2 = VINF_SUCCESS;
     2348
    21122349    if (RT_SUCCESS(rc))
    21132350        rc = rc2;
     
    24182655    HRESULT hr = S_OK;
    24192656
    2420     ComObjPtr <GuestDirectory> pDirectory;
    2421     int rc = directoryOpenInternal(Utf8Str(aPath), Utf8Str(aFilter), fFlags, pDirectory);
     2657    GuestDirectoryOpenInfo openInfo;
     2658    openInfo.mPath = Utf8Str(aPath);
     2659    openInfo.mFilter = Utf8Str(aFilter);
     2660    openInfo.mFlags = fFlags;
     2661
     2662    ComObjPtr <GuestDirectory> pDirectory; int guestRc;
     2663    int rc = directoryOpenInternal(openInfo, pDirectory, &guestRc);
    24222664    if (RT_SUCCESS(rc))
    24232665    {
     
    24332675                                                   Utf8Str(aPath).c_str()));
    24342676               break;
     2677
     2678            case VERR_GSTCTL_GUEST_ERROR:
     2679                hr = GuestDirectory::setErrorExternal(this, guestRc);
     2680                break;
    24352681
    24362682            default:
     
    25112757    LogFlowThisFuncEnter();
    25122758
    2513     AutoCaller autoCaller(this);
    2514     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2515 
    2516     ReturnComNotImplemented();
     2759    if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
     2760        return setError(E_INVALIDARG, tr("No directory to remove specified"));
     2761
     2762    AutoCaller autoCaller(this);
     2763    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2764
     2765    HRESULT hr = isReadyExternal();
     2766    if (FAILED(hr))
     2767        return hr;
     2768
     2769    /* No flags; only remove the directory when empty. */
     2770    uint32_t uFlags = 0;
     2771
     2772    int guestRc;
     2773    int vrc = directoryRemoveInternal(Utf8Str(aPath), uFlags, &guestRc);
     2774    if (RT_FAILURE(vrc))
     2775    {
     2776        switch (vrc)
     2777        {
     2778            case VERR_NOT_SUPPORTED:
     2779                hr = setError(VBOX_E_IPRT_ERROR,
     2780                              tr("Handling removing guest directories not supported by installed Guest Additions"));
     2781                break;
     2782
     2783            case VERR_GSTCTL_GUEST_ERROR:
     2784                hr = GuestDirectory::setErrorExternal(this, guestRc);
     2785                break;
     2786
     2787            default:
     2788                hr = setError(VBOX_E_IPRT_ERROR, tr("Removing guest directory \"%s\" failed: %Rrc"),
     2789                              Utf8Str(aPath).c_str(), vrc);
     2790                break;
     2791        }
     2792    }
     2793
     2794    return hr;
    25172795#endif /* VBOX_WITH_GUEST_CONTROL */
    25182796}
     
    25252803    LogFlowThisFuncEnter();
    25262804
    2527     AutoCaller autoCaller(this);
    2528     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2529 
    2530     ReturnComNotImplemented();
     2805    if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
     2806        return setError(E_INVALIDARG, tr("No directory to remove recursively specified"));
     2807
     2808    AutoCaller autoCaller(this);
     2809    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2810
     2811    HRESULT hr = isReadyExternal();
     2812    if (FAILED(hr))
     2813        return hr;
     2814
     2815    ComObjPtr<Progress> pProgress;
     2816    hr = pProgress.createObject();
     2817    if (SUCCEEDED(hr))
     2818        hr = pProgress->init(static_cast<IGuestSession *>(this),
     2819                             Bstr(tr("Removing guest directory")).raw(),
     2820                             TRUE /*aCancelable*/);
     2821    if (FAILED(hr))
     2822        return hr;
     2823
     2824    /* Note: At the moment we don't supply progress information while
     2825     *       deleting a guest directory recursively. So just complete
     2826     *       the progress object right now. */
     2827     /** @todo Implement progress reporting on guest directory deletion! */
     2828    hr = pProgress->notifyComplete(S_OK);
     2829    if (FAILED(hr))
     2830        return hr;
     2831
     2832    /* Remove the directory + all its contents. */
     2833    uint32_t uFlags = DIRREMOVE_FLAG_RECURSIVE
     2834                    | DIRREMOVE_FLAG_CONTENT_AND_DIR;
     2835    int guestRc;
     2836    int vrc = directoryRemoveInternal(Utf8Str(aPath), uFlags, &guestRc);
     2837    if (RT_FAILURE(vrc))
     2838    {
     2839        switch (vrc)
     2840        {
     2841            case VERR_NOT_SUPPORTED:
     2842                hr = setError(VBOX_E_IPRT_ERROR,
     2843                              tr("Handling removing guest directories recursively not supported by installed Guest Additions"));
     2844                break;
     2845
     2846            case VERR_GSTCTL_GUEST_ERROR:
     2847                hr = GuestFile::setErrorExternal(this, guestRc);
     2848                break;
     2849
     2850            default:
     2851                hr = setError(VBOX_E_IPRT_ERROR, tr("Recursively removing guest directory \"%s\" failed: %Rrc"),
     2852                              Utf8Str(aPath).c_str(), vrc);
     2853                break;
     2854        }
     2855    }
     2856    else
     2857    {
     2858        pProgress.queryInterfaceTo(aProgress);
     2859    }
     2860
     2861    return hr;
    25312862#endif /* VBOX_WITH_GUEST_CONTROL */
    25322863}
     
    25392870    LogFlowThisFuncEnter();
    25402871
    2541     AutoCaller autoCaller(this);
    2542     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2543 
    2544     ReturnComNotImplemented();
     2872    if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
     2873        return setError(E_INVALIDARG, tr("No source directory to rename specified"));
     2874
     2875    if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
     2876        return setError(E_INVALIDARG, tr("No destination directory to rename the source to specified"));
     2877
     2878    AutoCaller autoCaller(this);
     2879    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     2880
     2881    HRESULT hr = isReadyExternal();
     2882    if (FAILED(hr))
     2883        return hr;
     2884
     2885    /* No flags; only remove the directory when empty. */
     2886    uint32_t uFlags = 0;
     2887
     2888    int guestRc;
     2889    int vrc = pathRenameInternal(Utf8Str(aSource), Utf8Str(aDest), uFlags, &guestRc);
     2890    if (RT_FAILURE(vrc))
     2891    {
     2892        switch (vrc)
     2893        {
     2894            case VERR_NOT_SUPPORTED:
     2895                hr = setError(VBOX_E_IPRT_ERROR,
     2896                              tr("Handling renaming guest directories not supported by installed Guest Additions"));
     2897                break;
     2898
     2899            case VERR_GSTCTL_GUEST_ERROR:
     2900                hr = setError(VBOX_E_IPRT_ERROR,
     2901                              tr("Renaming guest directory failed: %Rrc"), guestRc);
     2902                break;
     2903
     2904            default:
     2905                hr = setError(VBOX_E_IPRT_ERROR, tr("Renaming guest directory \"%s\" failed: %Rrc"),
     2906                              Utf8Str(aSource).c_str(), vrc);
     2907                break;
     2908        }
     2909    }
     2910
     2911    return hr;
    25452912#endif /* VBOX_WITH_GUEST_CONTROL */
    25462913}
     
    29303297    LogFlowThisFuncEnter();
    29313298
    2932     AutoCaller autoCaller(this);
    2933     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    2934 
    2935     ReturnComNotImplemented();
     3299    if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
     3300        return setError(E_INVALIDARG, tr("No source file to rename specified"));
     3301
     3302    if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
     3303        return setError(E_INVALIDARG, tr("No destination file to rename the source to specified"));
     3304
     3305    AutoCaller autoCaller(this);
     3306    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     3307
     3308    HRESULT hr = isReadyExternal();
     3309    if (FAILED(hr))
     3310        return hr;
     3311
     3312    /* No flags; only remove the directory when empty. */
     3313    uint32_t uFlags = 0;
     3314
     3315    int guestRc;
     3316    int vrc = pathRenameInternal(Utf8Str(aSource), Utf8Str(aDest), uFlags, &guestRc);
     3317    if (RT_FAILURE(vrc))
     3318    {
     3319        switch (vrc)
     3320        {
     3321            case VERR_NOT_SUPPORTED:
     3322                hr = setError(VBOX_E_IPRT_ERROR,
     3323                              tr("Handling renaming guest files not supported by installed Guest Additions"));
     3324                break;
     3325
     3326            case VERR_GSTCTL_GUEST_ERROR:
     3327                /** @todo Proper guestRc to text translation needed. */
     3328                hr = setError(VBOX_E_IPRT_ERROR,
     3329                              tr("Renaming guest file failed: %Rrc"), guestRc);
     3330                break;
     3331
     3332            default:
     3333                hr = setError(VBOX_E_IPRT_ERROR, tr("Renaming guest file \"%s\" failed: %Rrc"),
     3334                              Utf8Str(aSource).c_str(), vrc);
     3335                break;
     3336        }
     3337    }
     3338
     3339    return hr;
    29363340#endif /* VBOX_WITH_GUEST_CONTROL */
    29373341}
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r47905 r49349  
    627627        {
    628628            GuestProcessStartupInfo procInfo;
    629             procInfo.mName    = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
    630                                                             mSource.c_str(), mDest.c_str(), objData.mObjectSize);
     629            procInfo.mName      = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" from guest to the host to \"%s\" (%RI64 bytes)"),
     630                                                              mSource.c_str(), mDest.c_str(), objData.mObjectSize);
    631631            procInfo.mCommand   = Utf8Str(VBOXSERVICE_TOOL_CAT);
    632632            procInfo.mFlags     = ProcessCreateFlag_Hidden | ProcessCreateFlag_WaitForStdOut;
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