VirtualBox

Ignore:
Timestamp:
Oct 20, 2015 10:05:12 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
103528
Message:

DnD: Updates/bugfixes:

  • Added separate VBOXDNDDISCONNECTMSG message for letting Main know about client disconnects.
  • Various cleanups and bugfixes.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/DragAndDrop/service.cpp

    r58257 r58329  
    3030#define LOG_GROUP LOG_GROUP_GUEST_DND
    3131
     32#include <algorithm>
     33#include <list>
    3234#include <map>
    3335
     
    4446*********************************************************************************************************************************/
    4547
    46 /** Map holding pointers to HGCM clients. Key is the (unique) HGCM client ID. */
    47 typedef std::map<uint32_t, HGCM::Client*> DnDClientMap;
     48class DragAndDropClient : public HGCM::Client
     49{
     50public:
     51
     52    DragAndDropClient(uint32_t uClientId, VBOXHGCMCALLHANDLE hHandle = NULL,
     53                      uint32_t uMsg = 0, uint32_t cParms = 0, VBOXHGCMSVCPARM aParms[] = NULL)
     54        : HGCM::Client(uClientId, hHandle, uMsg, cParms, aParms)
     55        , m_fDeferred(false)
     56    {
     57        RT_ZERO(m_SvcCtx);
     58    }
     59
     60    virtual ~DragAndDropClient(void)
     61    {
     62        disconnect();
     63    }
     64
     65public:
     66
     67    void complete(VBOXHGCMCALLHANDLE hHandle, int rcOp);
     68    void completeDeferred(int rcOp);
     69    void disconnect(void);
     70    bool isDeferred(void) const { return m_fDeferred; }
     71    void setDeferred(VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     72    void setSvcContext(const HGCM::VBOXHGCMSVCTX &SvcCtx) { m_SvcCtx = SvcCtx; }
     73
     74protected:
     75
     76    /** The HGCM service context this client is bound to. */
     77    HGCM::VBOXHGCMSVCTX m_SvcCtx;
     78    /** Flag indicating whether this client currently is deferred mode,
     79     *  meaning that it did not return to the caller yet. */
     80    bool                m_fDeferred;
     81};
     82
     83/** Map holding pointers to drag and drop clients. Key is the (unique) HGCM client ID. */
     84typedef std::map<uint32_t, DragAndDropClient*> DnDClientMap;
     85
     86/** Simple queue (list) which holds deferred (waiting) clients. */
     87typedef std::list<uint32_t> DnDClientQueue;
    4888
    4989/**
     
    68108
    69109    int modeSet(uint32_t u32Mode);
    70     inline uint32_t modeGet() { return m_u32Mode; };
     110    inline uint32_t modeGet(void) const { return m_u32Mode; };
    71111
    72112protected:
     
    76116protected:
    77117
    78     DnDManager             *m_pManager;
    79     /** Map of all connected clients. */
    80     DnDClientMap            m_clientMap;
     118    /** Pointer to our DnD manager instance. */
     119    DnDManager                        *m_pManager;
     120    /** Map of all connected clients.
     121     *  The primary key is the (unique) client ID, the secondary value
     122     *  an allocated pointer to the DragAndDropClient class, managed
     123     *  by this service class. */
     124    DnDClientMap                       m_clientMap;
    81125    /** List of all clients which are queued up (deferred return) and ready
    82      *  to process new commands. */
    83     RTCList<HGCM::Client*>  m_clientQueue;
    84     uint32_t                m_u32Mode;
     126     *  to process new commands. The key is the (unique) client ID. */
     127    DnDClientQueue                     m_clientQueue;
     128    /** Current drag and drop mode. */
     129    uint32_t                           m_u32Mode;
    85130};
    86131
     132
     133/*********************************************************************************************************************************
     134*   Client implementation                                                                                                        *
     135*********************************************************************************************************************************/
     136
     137/**
     138 * Completes the call by returning the control back to the guest
     139 * side code.
     140 */
     141void DragAndDropClient::complete(VBOXHGCMCALLHANDLE hHandle, int rcOp)
     142{
     143    LogFlowThisFunc(("uClientID=%RU32\n", m_uClientId));
     144
     145    if (   m_SvcCtx.pHelpers
     146        && m_SvcCtx.pHelpers->pfnCallComplete)
     147    {
     148        m_SvcCtx.pHelpers->pfnCallComplete(hHandle, rcOp);
     149    }
     150}
     151
     152/**
     153 * Completes a deferred call by returning the control back to the guest
     154 * side code.
     155 */
     156void DragAndDropClient::completeDeferred(int rcOp)
     157{
     158    AssertMsg(m_fDeferred, ("Client %RU32 is not in deferred mode\n", m_uClientId));
     159    Assert(m_hHandle != NULL);
     160
     161    LogFlowThisFunc(("uClientID=%RU32\n", m_uClientId));
     162
     163    complete(m_hHandle, rcOp);
     164    m_fDeferred = false;
     165}
     166
     167/**
     168 * Called when the HGCM client disconnected on the guest side.
     169 * This function takes care of the client's data cleanup and also lets the host
     170 * know that the client has been disconnected.
     171 *
     172 */
     173void DragAndDropClient::disconnect(void)
     174{
     175    LogFlowThisFunc(("uClient=%RU32\n", m_uClientId));
     176
     177    if (isDeferred())
     178        completeDeferred(VERR_INTERRUPTED);
     179
     180    /*
     181     * Let the host know.
     182     */
     183    VBOXDNDCBDISCONNECTMSGDATA data;
     184    RT_ZERO(data);
     185    /** @todo Magic needed? */
     186
     187    if (m_SvcCtx.pfnHostCallback)
     188    {
     189        int rc2 = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, GUEST_DND_DISCONNECT, &data, sizeof(data));
     190        if (RT_FAILURE(rc2))
     191            LogFlowFunc(("Warning: Unable to notify host about client %RU32 disconnect, rc=%Rrc\n", m_uClientId, rc2));
     192        /* Not fatal. */
     193    }
     194}
     195
     196/**
     197 * Set the client's status to deferred, meaning that it does not return to the caller
     198 * on the guest side yet.
     199 */
     200void DragAndDropClient::setDeferred(VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     201{
     202    LogFlowThisFunc(("uClient=%RU32\n", m_uClientId));
     203
     204    AssertMsg(m_fDeferred == false, ("Client already in deferred mode\n"));
     205    m_fDeferred = true;
     206
     207    m_hHandle = hHandle;
     208    m_uMsg    = u32Function;
     209    m_cParms  = cParms;
     210    m_paParms = paParms;
     211}
    87212
    88213/*********************************************************************************************************************************
     
    118243int DragAndDropService::uninit(void)
    119244{
     245    LogFlowFuncEnter();
     246
    120247    if (m_pManager)
    121248    {
     
    124251    }
    125252
     253    DnDClientMap::iterator itClient =  m_clientMap.begin();
     254    while (itClient != m_clientMap.end())
     255    {
     256        delete itClient->second;
     257        m_clientMap.erase(itClient);
     258        itClient = m_clientMap.begin();
     259    }
     260
     261    LogFlowFuncLeave();
    126262    return VINF_SUCCESS;
    127263}
     
    147283        try
    148284        {
    149             m_clientMap[u32ClientID] = new HGCM::Client(u32ClientID);
     285            DragAndDropClient *pClient = new DragAndDropClient(u32ClientID);
     286            pClient->setSvcContext(m_SvcCtx);
     287            m_clientMap[u32ClientID] = pClient;
    150288        }
    151289        catch(std::bad_alloc &)
     
    179317     * Remove from waiters queue.
    180318     */
    181     for (size_t i = 0; i < m_clientQueue.size(); i++)
    182     {
    183         HGCM::Client *pClient = m_clientQueue.at(i);
    184         if (pClient->clientId() == u32ClientID)
    185         {
    186             if (m_pHelpers)
    187                 m_pHelpers->pfnCallComplete(pClient->handle(), VERR_INTERRUPTED);
    188 
    189             m_clientQueue.removeAt(i);
    190             delete pClient;
    191 
    192             break;
    193         }
    194     }
     319    m_clientQueue.remove(u32ClientID);
    195320
    196321    /*
     
    208333int DragAndDropService::modeSet(uint32_t u32Mode)
    209334{
    210     /** @todo Validate mode. */
     335#ifndef VBOX_WITH_DRAG_AND_DROP_GH
     336    if (   u32Mode == VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST
     337        || u32Mode == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL)
     338    {
     339        m_u32Mode = VBOX_DRAG_AND_DROP_MODE_OFF;
     340        return VERR_NOT_SUPPORTED;
     341    }
     342#endif
     343
    211344    switch (u32Mode)
    212345    {
     
    308441#endif
    309442
    310 #define DO_HOST_CALLBACK();                                                     \
    311     if (   RT_SUCCESS(rc)                                                       \
    312         && m_pfnHostCallback)                                                   \
    313     {                                                                           \
    314         rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); \
     443#define DO_HOST_CALLBACK();                                                                   \
     444    if (   RT_SUCCESS(rc)                                                                     \
     445        && m_SvcCtx.pfnHostCallback)                                                          \
     446    {                                                                                         \
     447        rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, &data, sizeof(data)); \
     448    }
     449
     450    /*
     451     * Lookup client.
     452     */
     453    DragAndDropClient *pClient = NULL;
     454
     455    DnDClientMap::iterator itClient =  m_clientMap.find(u32ClientID);
     456    if (itClient != m_clientMap.end())
     457    {
     458        pClient = itClient->second;
     459        AssertPtr(pClient);
     460    }
     461    else
     462    {
     463        LogFunc(("Client %RU32 was not found\n", u32ClientID));
     464        rc = VERR_NOT_FOUND;
    315465    }
    316466
    317467    if (rc == VINF_SUCCESS) /* Note: rc might be VINF_HGCM_ASYNC_EXECUTE! */
    318468    {
    319         DnDClientMap::iterator itClient =  m_clientMap.find(u32ClientID);
    320         Assert(itClient != m_clientMap.end());
    321 
    322         HGCM::Client *pClient = itClient->second;
    323         AssertPtr(pClient);
    324 
    325469        LogFlowFunc(("Client %RU32: Protocol v%RU32\n", pClient->clientId(), pClient->protocol()));
    326470
     
    344488                    if (RT_FAILURE(rc)) /* No queued messages available? */
    345489                    {
    346                         if (m_pfnHostCallback) /* Try asking the host. */
     490                        if (m_SvcCtx.pfnHostCallback) /* Try asking the host. */
    347491                        {
    348492                            VBOXDNDCBHGGETNEXTHOSTMSG data;
    349493                            RT_ZERO(data);
    350494                            data.hdr.uMagic = CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG;
    351                             rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
     495                            rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, &data, sizeof(data));
    352496                            if (RT_SUCCESS(rc))
    353497                            {
     
    366510                        if (RT_FAILURE(rc))
    367511                        {
    368                             if (paParms[2].u.uint32) /* Blocking flag set? */
     512                            uint32_t fFlags = 0;
     513                            int rc2 = paParms[2].getUInt32(&fFlags);
     514                            if (   RT_SUCCESS(rc2)
     515                                && fFlags) /* Blocking flag set? */
    369516                            {
    370517                                /* Defer client returning. */
    371518                                rc = VINF_HGCM_ASYNC_EXECUTE;
    372519                            }
     520                            else
     521                                rc = VERR_INVALID_PARAMETER;
    373522
    374523                            LogFlowFunc(("Message queue is empty, returning %Rrc to guest\n", rc));
     
    390539                    if (cParms >= 3)
    391540                        rc = paParms[0].getUInt32(&data.hdr.uContextID);
     541                    else /* Older protocols don't have a context ID. */
     542                        rc = VINF_SUCCESS;
    392543                    if (RT_SUCCESS(rc))
    393544                        rc = paParms[idxProto].getUInt32(&data.uProtocol);
     
    660811                            rc = paParms[0].getUInt32(&data.hdr.uContextID);
    661812                            if (RT_SUCCESS(rc))
    662                                 rc = paParms[0].getPointer((void**)&data.pszPath, &data.cbPath);
    663                             if (RT_SUCCESS(rc))
    664                                 rc = paParms[1].getUInt32(&data.cbPath);
    665                             if (RT_SUCCESS(rc))
    666                                 rc = paParms[2].getUInt32(&data.fMode);
     813                                rc = paParms[1].getPointer((void**)&data.pszPath, &data.cbPath);
     814                            if (RT_SUCCESS(rc))
     815                                rc = paParms[2].getUInt32(&data.cbPath);
     816                            if (RT_SUCCESS(rc))
     817                                rc = paParms[3].getUInt32(&data.fMode);
    667818                        }
    668819                        break;
     
    842993                if (rc == VERR_NO_DATA) /* Manager has no new messsages? Try asking the host. */
    843994                {
    844                     if (m_pfnHostCallback)
     995                    if (m_SvcCtx.pfnHostCallback)
    845996                    {
    846997                        VBOXDNDCBHGGETNEXTHOSTMSGDATA data;
     
    8511002                        data.paParms = paParms;
    8521003
    853                         rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
     1004                        rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function,
     1005                                                      &data, sizeof(data));
    8541006                        if (RT_SUCCESS(rc))
    8551007                        {
     
    8751027        try
    8761028        {
    877             LogFlowFunc(("Deferring guest call completion of client ID=%RU32\n", u32ClientID));
    878             m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle,
    879                                                   u32Function, cParms, paParms));
     1029            AssertPtr(pClient);
     1030            pClient->setDeferred(callHandle, u32Function, cParms, paParms);
     1031            m_clientQueue.push_back(u32ClientID);
    8801032        }
    8811033        catch (std::bad_alloc)
     
    8851037        }
    8861038    }
    887     else if (m_pHelpers)
    888     {
    889         /* Complete call on guest side. */
    890         m_pHelpers->pfnCallComplete(callHandle, rc);
    891     }
     1039    else if (pClient)
     1040        pClient->complete(callHandle, rc);
    8921041    else
    8931042        rc = VERR_NOT_IMPLEMENTED;
     
    9211070                if (m_clientQueue.size()) /* Any clients in our queue ready for processing the next command? */
    9221071                {
    923                     HGCM::Client *pClient = m_clientQueue.first();
     1072                    uint32_t uClientNext = m_clientQueue.front();
     1073                    DnDClientMap::iterator itClientNext = m_clientMap.find(uClientNext);
     1074                    Assert(itClientNext != m_clientMap.end());
     1075
     1076                    DragAndDropClient *pClient = itClientNext->second;
    9241077                    AssertPtr(pClient);
    9251078
     
    9391092                        if (RT_SUCCESS(rc))
    9401093                        {
    941                             pClient->addMessageInfo(uMsg1, cParms1);
    942                             if (   m_pHelpers
    943                                 && m_pHelpers->pfnCallComplete)
    944                             {
    945                                 m_pHelpers->pfnCallComplete(pClient->handle(), rc);
    946                             }
    947 
    948                             m_clientQueue.removeFirst();
    949 
    950                             delete pClient;
    951                             pClient = NULL;
    952                         }
    953                         else
    954                             AssertMsgFailed(("m_pManager::nextMessageInfo failed with rc=%Rrc\n", rc));
     1094                            rc = pClient->addMessageInfo(uMsg1, cParms1);
     1095
     1096                            /* Note: Report the current rc back to the guest. */
     1097                            pClient->completeDeferred(rc);
     1098
     1099                            m_clientQueue.pop_front();
     1100                        }
    9551101                    }
    9561102                    else
     
    9921138    AssertPtr(pSelf);
    9931139
    994     if (pSelf->m_pfnHostCallback)
     1140    if (pSelf->m_SvcCtx.pfnHostCallback)
    9951141    {
    9961142        LogFlowFunc(("GUEST_DND_HG_EVT_PROGRESS: uStatus=%RU32, uPercentage=%RU32, rc=%Rrc\n",
     
    10031149        data.rc           = rc; /** @todo uin32_t vs. int. */
    10041150
    1005         return pSelf->m_pfnHostCallback(pSelf->m_pvHostData,
    1006                                         GUEST_DND_HG_EVT_PROGRESS,
    1007                                         &data, sizeof(data));
     1151        return pSelf->m_SvcCtx.pfnHostCallback(pSelf->m_SvcCtx.pvHostData,
     1152                                               GUEST_DND_HG_EVT_PROGRESS,
     1153                                               &data, sizeof(data));
    10081154    }
    10091155
Note: See TracChangeset for help on using the changeset viewer.

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