VirtualBox

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


Ignore:
Timestamp:
Feb 24, 2023 8:49:40 AM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
156009
Message:

Guest Control: Implemented directory handling / walking as non-toolbox variants. bugref:9783

Location:
trunk/src/VBox/Main/src-client
Files:
2 edited

Legend:

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

    r98667 r98709  
    4747
    4848#include <VBox/com/array.h>
     49#include <VBox/com/listeners.h>
    4950#include <VBox/AssertGuest.h>
    5051
     52
     53/**
     54 * Internal listener class to serve events in an
     55 * active manner, e.g. without polling delays.
     56 */
     57class GuestDirectoryListener
     58{
     59public:
     60
     61    GuestDirectoryListener(void)
     62    {
     63    }
     64
     65    virtual ~GuestDirectoryListener()
     66    {
     67    }
     68
     69    HRESULT init(GuestDirectory *pDir)
     70    {
     71        AssertPtrReturn(pDir, E_POINTER);
     72        mDir = pDir;
     73        return S_OK;
     74    }
     75
     76    void uninit(void)
     77    {
     78        mDir = NULL;
     79    }
     80
     81    STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
     82    {
     83        switch (aType)
     84        {
     85            case VBoxEventType_OnGuestDirectoryStateChanged:
     86                RT_FALL_THROUGH();
     87            case VBoxEventType_OnGuestDirectoryRead:
     88            {
     89                AssertPtrReturn(mDir, E_POINTER);
     90                int vrc2 = mDir->signalWaitEvent(aType, aEvent);
     91                RT_NOREF(vrc2);
     92#ifdef DEBUG_andy
     93                LogFlowFunc(("Signalling events of type=%RU32, dir=%p resulted in vrc=%Rrc\n",
     94                             aType, mDir, vrc2));
     95#endif
     96                break;
     97            }
     98
     99            default:
     100                AssertMsgFailed(("Unhandled event %RU32\n", aType));
     101                break;
     102        }
     103
     104        return S_OK;
     105    }
     106
     107private:
     108
     109    /** Weak pointer to the guest directory object to listen for. */
     110    GuestDirectory *mDir;
     111};
     112typedef ListenerImpl<GuestDirectoryListener, GuestDirectory *> GuestDirectoryListenerImpl;
     113
     114VBOX_LISTENER_DECLARE(GuestDirectoryListenerImpl)
    51115
    52116// constructor / destructor
     
    98162        if (FAILED(hr))
    99163            vrc = VERR_COM_UNEXPECTED;
     164    }
     165
     166    if (RT_SUCCESS(vrc))
     167    {
     168        try
     169        {
     170            GuestDirectoryListener *pListener = new GuestDirectoryListener();
     171            ComObjPtr<GuestDirectoryListenerImpl> thisListener;
     172            HRESULT hr = thisListener.createObject();
     173            if (SUCCEEDED(hr))
     174                hr = thisListener->init(pListener, this);
     175
     176            if (SUCCEEDED(hr))
     177            {
     178                com::SafeArray <VBoxEventType_T> eventTypes;
     179                eventTypes.push_back(VBoxEventType_OnGuestDirectoryStateChanged);
     180                eventTypes.push_back(VBoxEventType_OnGuestDirectoryRead);
     181                hr = mEventSource->RegisterListener(thisListener,
     182                                                    ComSafeArrayAsInParam(eventTypes),
     183                                                    TRUE /* Active listener */);
     184                if (SUCCEEDED(hr))
     185                {
     186                    vrc = baseInit();
     187                    if (RT_SUCCESS(vrc))
     188                    {
     189                        mLocalListener = thisListener;
     190                    }
     191                }
     192                else
     193                    vrc = VERR_COM_UNEXPECTED;
     194            }
     195            else
     196                vrc = VERR_COM_UNEXPECTED;
     197        }
     198        catch(std::bad_alloc &)
     199        {
     200            vrc = VERR_NO_MEMORY;
     201        }
    100202    }
    101203
     
    194296    AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
    195297
    196     LogFlowThisFunc(("strPath=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
     298    LogFlowThisFunc(("strPath=%s, uContextID=%RU32, uMessage=%RU32, pSvcCb=%p\n",
    197299                     mData.mOpenInfo.mPath.c_str(), pCbCtx->uContextID, pCbCtx->uMessage, pSvcCb));
    198300
     
    248350        }
    249351
     352        if (RT_FAILURE(vrc))
     353            return vrc;
     354
    250355        /* Prepare HGCM call. */
    251356        VBOXHGCMSVCPARM paParms[8];
    252357        int i = 0;
    253358        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
    254         HGCMSvcSetPv(&paParms[i++], (void *)mData.mOpenInfo.mPath.c_str(), (ULONG)mData.mOpenInfo.mPath.length() + 1);
    255         HGCMSvcSetPv(&paParms[i++], (void *)mData.mOpenInfo.mFilter.c_str(), (ULONG)mData.mOpenInfo.mFilter.length() + 1);
     359        HGCMSvcSetStr(&paParms[i++], mData.mOpenInfo.mPath.c_str());
    256360        HGCMSvcSetU32(&paParms[i++], mData.mOpenInfo.menmFilter);
    257361        HGCMSvcSetU32(&paParms[i++], mData.mOpenInfo.mFlags);
     
    261365        vrc = sendMessage(HOST_MSG_DIR_OPEN, i, paParms);
    262366        if (RT_SUCCESS(vrc))
    263         {
    264             vrc = pEvent->Wait(30 * 1000);
    265             if (RT_SUCCESS(vrc))
    266             {
    267             }
    268         }
     367            vrc = i_waitForStatusChange(pEvent, 30 * 1000, NULL /* FileStatus */, pvrcGuest);
    269368    }
    270369    else
     
    385484    {
    386485        hrc = errorInfo->initEx(VBOX_E_GSTCTL_GUEST_ERROR, vrcGuest,
    387                                 COM_IIDOF(IGuestFile), getComponentName(),
     486                                COM_IIDOF(IGuestDirectory), getComponentName(),
    388487                                i_guestErrorToString(vrcGuest, mData.mOpenInfo.mPath.c_str()));
    389488        ComAssertComRCRet(hrc, VERR_COM_UNEXPECTED);
     
    400499        case GUEST_DIR_NOTIFYTYPE_OPEN:
    401500        {
     501            AssertBreakStmt(pSvcCbData->mParms >= 4, vrc = VERR_INVALID_PARAMETER);
     502            vrc = HGCMSvcGetU32(&pSvcCbData->mpaParms[idx++], &dataCb.u.open.uHandle /* Guest native file handle */);
     503            AssertRCBreak(vrc);
    402504            vrc = i_setStatus(DirectoryStatus_Open, vrcGuest);
    403505            break;
     
    417519                                        ("type=%u\n", pSvcCbData->mpaParms[idx].type),
    418520                                        vrc = VERR_WRONG_PARAMETER_TYPE);
    419 
    420             PGSTCTLFSOBJINFO pObjInfo;
    421             uint32_t         cbObjInfo;
    422             vrc = HGCMSvcGetPv(&pSvcCbData->mpaParms[idx++], (void **)&pObjInfo, &cbObjInfo);
     521            PGSTCTLDIRENTRYEX pEntry;
     522            uint32_t          cbEntry;
     523            vrc = HGCMSvcGetPv(&pSvcCbData->mpaParms[idx++], (void **)&pEntry, &cbEntry);
    423524            AssertRCBreak(vrc);
    424             AssertBreakStmt(cbObjInfo == sizeof(GSTCTLFSOBJINFO), VERR_INVALID_PARAMETER);
    425 
    426             GuestFsObjData fsObjData(mData.mOpenInfo.mPath);
    427             vrc = fsObjData.FromGuestFsObjInfo(pObjInfo);
     525            AssertBreakStmt(   cbEntry >= sizeof(GSTCTLDIRENTRYEX)
     526                            && cbEntry <= GSTCTL_DIRENTRY_MAX_SIZE, VERR_INVALID_PARAMETER);
     527            dataCb.u.read.pEntry  = (PGSTCTLDIRENTRYEX)RTMemDup(pEntry, cbEntry);
     528            AssertPtrBreakStmt(dataCb.u.read.pEntry, vrc = VERR_NO_MEMORY);
     529            dataCb.u.read.cbEntry = cbEntry;
     530
     531            char    *pszUser;
     532            uint32_t cbUser;
     533            vrc = HGCMSvcGetStr(&pSvcCbData->mpaParms[idx++], &pszUser, &cbUser);
     534            AssertRCBreak(vrc);
     535            dataCb.u.read.pszUser = RTStrDup(pszUser);
     536            AssertPtrBreakStmt(dataCb.u.read.pszUser, vrc = VERR_NO_MEMORY);
     537            dataCb.u.read.cbUser  = cbUser;
     538
     539            char    *pszGroups;
     540            uint32_t cbGroups;
     541            vrc = HGCMSvcGetStr(&pSvcCbData->mpaParms[idx++], &pszGroups, &cbGroups);
     542            AssertRCBreak(vrc);
     543            dataCb.u.read.pszGroups = RTStrDup(pszGroups);
     544            AssertPtrBreakStmt(dataCb.u.read.pszGroups, vrc = VERR_NO_MEMORY);
     545            dataCb.u.read.cbGroups  = cbGroups;
     546
     547            /** @todo ACLs not implemented yet. */
     548
     549            GuestFsObjData fsObjData(dataCb.u.read.pEntry->szName);
     550            vrc = fsObjData.FromGuestFsObjInfo(&dataCb.u.read.pEntry->Info);
    428551            AssertRCBreak(vrc);
    429552            ComObjPtr<GuestFsObjInfo> ptrFsObjInfo;
    430553            hrc = ptrFsObjInfo.createObject();
    431             ComAssertComRCBreak(hrc, VERR_COM_UNEXPECTED);
     554            ComAssertComRCBreak(hrc, vrc = VERR_COM_UNEXPECTED);
    432555            vrc = ptrFsObjInfo->init(fsObjData);
    433556            AssertRCBreak(vrc);
    434557
    435             ::FireGuestDirectoryReadEvent(mEventSource, mSession, this, ptrFsObjInfo);
     558            ::FireGuestDirectoryReadEvent(mEventSource, mSession, this,
     559                                          dataCb.u.read.pEntry->szName, ptrFsObjInfo, dataCb.u.read.pszUser, dataCb.u.read.pszGroups);
    436560            break;
    437561        }
     
    481605 *
    482606 * @returns Error string.
    483  * @param   vrcGuest            Guest file error to return string for.
     607 * @param   vrcGuest            Guest directory error to return string for.
    484608 * @param   pcszWhat            Hint of what was involved when the error occurred.
    485609 */
     
    550674    if (mSession->i_getParent()->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
    551675    {
    552         /// @todo To be implemented
    553         vrc = VERR_NOT_IMPLEMENTED;
     676        GuestWaitEvent *pEvent = NULL;
     677        GuestEventTypes eventTypes;
     678        try
     679        {
     680            eventTypes.push_back(VBoxEventType_OnGuestDirectoryStateChanged);
     681
     682            vrc = registerWaitEvent(eventTypes, &pEvent);
     683        }
     684        catch (std::bad_alloc &)
     685        {
     686            vrc = VERR_NO_MEMORY;
     687        }
     688
     689        if (RT_FAILURE(vrc))
     690            return vrc;
     691
     692        /* Prepare HGCM call. */
     693        VBOXHGCMSVCPARM paParms[2];
     694        int i = 0;
     695        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     696        HGCMSvcSetU32(&paParms[i++], mObjectID /* Guest directory handle */);
     697
     698        vrc = sendMessage(HOST_MSG_DIR_CLOSE, i, paParms);
     699        if (RT_SUCCESS(vrc))
     700        {
     701            vrc = pEvent->Wait(30 * 1000);
     702            if (RT_SUCCESS(vrc))
     703            {
     704                // Nothing to do here.
     705            }
     706            else if (pEvent->HasGuestError() && pvrcGuest)
     707                *pvrcGuest = pEvent->GuestResult();
     708        }
    554709    }
    555710    else
     
    595750
    596751    int vrc;
     752    int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS;
     753
    597754#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
    598755    if (mSession->i_getParent()->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS)
    599756    {
    600         /// @todo To be implemented
    601         RT_NOREF(objData, pvrcGuest);
    602         vrc = 0;
     757        GuestWaitEvent *pEvent = NULL;
     758        GuestEventTypes eventTypes;
     759        try
     760        {
     761            vrc = registerWaitEvent(eventTypes, &pEvent);
     762        }
     763        catch (std::bad_alloc &)
     764        {
     765            vrc = VERR_NO_MEMORY;
     766        }
     767
     768        if (RT_FAILURE(vrc))
     769            return vrc;
     770
     771        /* Prepare HGCM call. */
     772        VBOXHGCMSVCPARM paParms[8];
     773        int i = 0;
     774        HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     775        HGCMSvcSetU32(&paParms[i++], mObjectID /* Guest directory handle */);
     776        HGCMSvcSetU32(&paParms[i++], GSTCTL_DIRENTRY_MAX_SIZE);
     777        HGCMSvcSetU32(&paParms[i++], GSTCTLFSOBJATTRADD_UNIX /* Implicit */);
     778        HGCMSvcSetU32(&paParms[i++], GSTCTL_PATH_F_ON_LINK);
     779
     780        vrc = sendMessage(HOST_MSG_DIR_READ, i, paParms);
     781        if (RT_SUCCESS(vrc))
     782        {
     783            vrc = pEvent->Wait(30 * 1000);
     784            if (RT_SUCCESS(vrc))
     785            {
     786                PCALLBACKDATA_DIR_NOTIFY const pDirNotify = (PCALLBACKDATA_DIR_NOTIFY)pEvent->Payload().Raw();
     787                AssertPtrReturn(pDirNotify, VERR_INVALID_POINTER);
     788                vrcGuest = (int)pDirNotify->rc;
     789                if (RT_SUCCESS(vrcGuest))
     790                {
     791                    AssertReturn(pDirNotify->uType == GUEST_DIR_NOTIFYTYPE_READ, VERR_INVALID_PARAMETER);
     792                    AssertPtrReturn(pDirNotify->u.read.pEntry, VERR_INVALID_POINTER);
     793                    objData.Init(pDirNotify->u.read.pEntry->szName);
     794                    vrc = objData.FromGuestFsObjInfo(&pDirNotify->u.read.pEntry->Info,
     795                                                     pDirNotify->u.read.pszUser, pDirNotify->u.read.pszGroups);
     796                    RTMemFree(pDirNotify->u.read.pEntry);
     797                    RTStrFree(pDirNotify->u.read.pszUser);
     798                    RTStrFree(pDirNotify->u.read.pszGroups);
     799                }
     800                else
     801                {
     802                    if (pvrcGuest)
     803                        *pvrcGuest = vrcGuest;
     804                    vrc = VERR_GSTCTL_GUEST_ERROR;
     805                }
     806            }
     807            else if (pEvent->HasGuestError() && pvrcGuest)
     808                *pvrcGuest = pEvent->GuestResult();
     809        }
    603810    }
    604811    else
     
    8131020        alock.release(); /* Release lock before firing off event. */
    8141021
    815         ::FireGuestDirectoryStateChangedEvent(mEventSource, mSession, this, enmStatus, errorInfo);
     1022        ::FireGuestDirectoryStateChangedEvent(mEventSource, mSession, this, mData.mStatus, errorInfo);
    8161023    }
    8171024
    8181025    return VINF_SUCCESS;
     1026}
     1027
     1028/**
     1029 * Waits for a guest directory status change.
     1030 *
     1031 * @note Similar code in GuestFile::i_waitForStatusChange().
     1032 *
     1033 * @returns VBox status code.
     1034 * @retval  VERR_GSTCTL_GUEST_ERROR when an error from the guest side has been received.
     1035 * @param   pEvent              Guest wait event to wait for.
     1036 * @param   uTimeoutMS          Timeout (in ms) to wait.
     1037 * @param   penmStatus          Where to return the directoy status on success.
     1038 * @param   prcGuest            Where to return the guest error when VERR_GSTCTL_GUEST_ERROR was returned.
     1039 */
     1040int GuestDirectory::i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
     1041                                          DirectoryStatus_T *penmStatus, int *prcGuest)
     1042{
     1043    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     1044    /* penmStatus is optional. */
     1045
     1046    VBoxEventType_T evtType;
     1047    ComPtr<IEvent>  pIEvent;
     1048    int vrc = waitForEvent(pEvent, uTimeoutMS, &evtType, pIEvent.asOutParam());
     1049    if (RT_SUCCESS(vrc))
     1050    {
     1051        AssertReturn(evtType == VBoxEventType_OnGuestDirectoryStateChanged, VERR_WRONG_TYPE);
     1052        ComPtr<IGuestDirectoryStateChangedEvent> pDirectoryEvent = pIEvent;
     1053        AssertReturn(!pDirectoryEvent.isNull(), VERR_COM_UNEXPECTED);
     1054
     1055        HRESULT hr;
     1056        if (penmStatus)
     1057        {
     1058            hr = pDirectoryEvent->COMGETTER(Status)(penmStatus);
     1059            ComAssertComRC(hr);
     1060        }
     1061
     1062        ComPtr<IVirtualBoxErrorInfo> errorInfo;
     1063        hr = pDirectoryEvent->COMGETTER(Error)(errorInfo.asOutParam());
     1064        ComAssertComRC(hr);
     1065
     1066        LONG lGuestRc;
     1067        hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
     1068        ComAssertComRC(hr);
     1069
     1070        LogFlowThisFunc(("resultDetail=%RI32 (%Rrc)\n", lGuestRc, lGuestRc));
     1071
     1072        if (RT_FAILURE((int)lGuestRc))
     1073            vrc = VERR_GSTCTL_GUEST_ERROR;
     1074
     1075        if (prcGuest)
     1076            *prcGuest = (int)lGuestRc;
     1077    }
     1078    /* waitForEvent may also return VERR_GSTCTL_GUEST_ERROR like we do above, so make prcGuest is set. */
     1079    /** @todo Also see todo in GuestFile::i_waitForStatusChange(). */
     1080    else if (vrc == VERR_GSTCTL_GUEST_ERROR && prcGuest)
     1081        *prcGuest = pEvent->GuestResult();
     1082    Assert(vrc != VERR_GSTCTL_GUEST_ERROR || !prcGuest || *prcGuest != (int)0xcccccccc);
     1083
     1084    return vrc;
    8191085}
    8201086
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r98667 r98709  
    19791979            return vrc;
    19801980
    1981         uint32_t const fFlags = fFollowSymlinks ? GSTCTL_QUERYINFO_F_FOLLOW_LINK : GSTCTL_QUERYINFO_F_ON_LINK;
     1981        uint32_t const fFlags = fFollowSymlinks ? GSTCTL_PATH_F_FOLLOW_LINK : GSTCTL_PATH_F_ON_LINK;
    19821982
    19831983        /* Prepare HGCM call. */
     
    22712271            case GUEST_FS_NOTIFYTYPE_QUERY_INFO:
    22722272            {
    2273                 AssertBreakStmt(pSvcCbData->mParms >= 7, VERR_INVALID_PARAMETER);
     2273                AssertBreakStmt(pSvcCbData->mParms >= 7, vrc = VERR_INVALID_PARAMETER);
    22742274                PGSTCTLFSOBJINFO pObjInfo;
    22752275                uint32_t         cbObjInfo;
    22762276                vrc = HGCMSvcGetPv(&pSvcCbData->mpaParms[3], (void **)&pObjInfo, &cbObjInfo);
    22772277                AssertRCBreak(vrc);
    2278                 AssertBreakStmt(cbObjInfo == sizeof(GSTCTLFSOBJINFO), VERR_INVALID_PARAMETER);
     2278                AssertBreakStmt(cbObjInfo == sizeof(GSTCTLFSOBJINFO), vrc = VERR_INVALID_PARAMETER);
    22792279                memcpy(&dataCb.u.QueryInfo.objInfo, pObjInfo, sizeof(GSTCTLFSOBJINFO));
    22802280
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