VirtualBox

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


Ignore:
Timestamp:
Feb 19, 2014 3:45:58 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
92350
Message:

DnD: Update.

File:
1 edited

Legend:

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

    r50460 r50508  
    191191    Utf8Str format(void) const { return m_strFormat; }
    192192
    193     int dataAdd(void *pvData, uint32_t cbData, uint32_t *pcbCurSize);
     193    void setDropDir(const Utf8Str &strDropDir) { m_strDropDir = strDropDir; }
     194    Utf8Str dropDir(void) const { return m_strDropDir; }
     195
     196    int dataAdd(const void *pvData, uint32_t cbData, uint32_t *pcbCurSize);
     197    int dataSetStatus(size_t cbDataAdd, size_t cbDataTotal = 0);
    194198    void reset(void);
    195199    const void *data(void) { return m_pvData; }
     
    205209    uint32_t             m_allActions;
    206210    Utf8Str              m_strFormat;
     211
     212    /** The actual MIME data.*/
    207213    void                *m_pvData;
     214    /** Size (in bytes) of MIME data. */
    208215    uint32_t             m_cbData;
     216
     217    size_t               m_cbDataCurrent;
     218    size_t               m_cbDataTotal;
     219    /** Dropped files directory on the host. */
     220    Utf8Str              m_strDropDir;
    209221
    210222    ComObjPtr<Guest>     m_parent;
     
    276288  , m_pvData(0)
    277289  , m_cbData(0)
     290  , m_cbDataCurrent(0)
     291  , m_cbDataTotal(0)
    278292  , m_parent(pGuest)
    279293{
     
    303317}
    304318
    305 int DnDGuestResponse::dataAdd(void *pvData, uint32_t cbData, uint32_t *pcbCurSize)
    306 {
     319int DnDGuestResponse::dataAdd(const void *pvData, uint32_t cbData,
     320                              uint32_t *pcbCurSize)
     321{
     322    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
     323    AssertReturn(cbData, VERR_INVALID_PARAMETER);
     324    /* pcbCurSize is optional. */
     325
    307326    int rc = VINF_SUCCESS;
    308327
     
    348367}
    349368
    350 int DnDGuestResponse::setProgress(unsigned uPercentage, uint32_t uState, int rcOp /* = VINF_SUCCESS */)
    351 {
    352     LogFlowFunc(("uPercentage=%RU32, uState=%ld, rcOp=%Rrc\n", uPercentage, uState, rcOp));
     369int DnDGuestResponse::setProgress(unsigned uPercentage,
     370                                  uint32_t uState, int rcOp /* = VINF_SUCCESS */)
     371{
     372    LogFlowFunc(("uPercentage=%RU32, uState=%ld, rcOp=%Rrc\n",
     373                 uPercentage, uState, rcOp));
    353374
    354375    int vrc = VINF_SUCCESS;
     
    364385                                                COM_IIDOF(IGuest),
    365386                                                m_parent->getComponentName(),
    366                                                 m_parent->tr("Guest error (%Rrc)"), rcOp);
     387                                                m_parent->tr("Drag'n drop guest error (%Rrc)"), rcOp);
    367388            }
    368389            else if (uState == DragAndDropSvc::DND_PROGRESS_CANCELLED)
     
    390411}
    391412
     413int DnDGuestResponse::dataSetStatus(size_t cbDataAdd, size_t cbDataTotal /* = 0 */)
     414{
     415    if (cbDataTotal)
     416    {
     417        AssertMsg(m_cbDataTotal <= cbDataTotal, ("New data size size must not be smaller (%zu) than old value (%zu)\n",
     418                                                 cbDataTotal, m_cbDataTotal));
     419        m_cbDataTotal = cbDataTotal;
     420        LogFlowFunc(("Updating total data size to: %zu\n", m_cbDataTotal));
     421    }
     422    AssertMsg(m_cbDataTotal, ("m_cbDataTotal must not be <= 0\n"));
     423
     424    m_cbDataCurrent += cbDataAdd;
     425    unsigned int cPercentage = RT_MIN(m_cbDataCurrent * 100.0 / m_cbDataTotal, 100);
     426
     427    /** @todo Don't use anonymous enums (uint32_t). */
     428    uint32_t uStatus = DragAndDropSvc::DND_PROGRESS_RUNNING;
     429    if (m_cbDataCurrent >= m_cbDataTotal)
     430        uStatus = DragAndDropSvc::DND_PROGRESS_COMPLETE;
     431
     432#ifdef DEBUG_andy
     433    LogFlowFunc(("Updating transfer status (%zu/%zu), status=%ld\n",
     434                 m_cbDataCurrent, m_cbDataTotal, uStatus));
     435#endif
     436
     437    AssertMsg(m_cbDataCurrent <= m_cbDataTotal,
     438              ("More data transferred (%RU32) than initially announced (%RU32)\n",
     439              m_cbDataCurrent, m_cbDataTotal));
     440
     441    int rc = setProgress(cPercentage, uStatus);
     442
     443    /** @todo For now we instantly confirm the cancel. Check if the
     444     *        guest should first clean up stuff itself and than really confirm
     445     *        the cancel request by an extra message. */
     446    if (rc == VERR_CANCELLED)
     447        rc = setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED);
     448
     449    return rc;
     450}
     451
    392452HRESULT DnDGuestResponse::queryProgressTo(IProgress **ppProgress)
    393453{
     
    503563
    504564/* static */
    505 void GuestDnDPrivate::toHGCMActions(DragAndDropAction_T inDefAction, uint32_t *pOutDefAction, ComSafeArrayIn(DragAndDropAction_T, inAllowedActions), uint32_t *pOutAllowedActions)
     565void GuestDnDPrivate::toHGCMActions(DragAndDropAction_T inDefAction,
     566                                    uint32_t *pOutDefAction,
     567                                    ComSafeArrayIn(DragAndDropAction_T, inAllowedActions),
     568                                    uint32_t *pOutAllowedActions)
    506569{
    507570    const com::SafeArray<DragAndDropAction_T> sfaInActions(ComSafeArrayInArg(inAllowedActions));
     
    529592DragAndDropAction_T GuestDnDPrivate::toMainAction(uint32_t uAction)
    530593{
    531     /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */
     594    /* For now it doesn't seems useful to allow a
     595     * link action between host & guest. Maybe later! */
    532596    return (isDnDCopyAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Copy :
    533597            isDnDMoveAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Move :
     
    536600
    537601/* static */
    538 void GuestDnDPrivate::toMainActions(uint32_t uActions, ComSafeArrayOut(DragAndDropAction_T, actions))
    539 {
    540     /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */
     602void GuestDnDPrivate::toMainActions(uint32_t uActions,
     603                                    ComSafeArrayOut(DragAndDropAction_T, actions))
     604{
     605    /* For now it doesn't seems useful to allow a
     606     * link action between host & guest. Maybe later! */
    541607    RTCList<DragAndDropAction_T> list;
    542608    if (hasDnDCopyAction(uActions))
     
    556622}
    557623
    558 GuestDnD::~GuestDnD()
     624GuestDnD::~GuestDnD(void)
    559625{
    560626    delete d_ptr;
    561627}
    562628
    563 HRESULT GuestDnD::dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
     629HRESULT GuestDnD::dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY,
     630                              DragAndDropAction_T defaultAction,
     631                              ComSafeArrayIn(DragAndDropAction_T, allowedActions),
     632                              ComSafeArrayIn(IN_BSTR, formats),
     633                              DragAndDropAction_T *pResultAction)
    564634{
    565635    DPTR(GuestDnD);
     
    621691}
    622692
    623 HRESULT GuestDnD::dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
     693HRESULT GuestDnD::dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY,
     694                             DragAndDropAction_T defaultAction,
     695                             ComSafeArrayIn(DragAndDropAction_T, allowedActions),
     696                             ComSafeArrayIn(IN_BSTR, formats),
     697                             DragAndDropAction_T *pResultAction)
    624698{
    625699    DPTR(GuestDnD);
     
    879953
    880954    const char *pcszFormat = strFormat.c_str();
    881     LogFlowFunc(("strFormat=%s, uAction=0x%x\n", pcszFormat, uAction));
    882     if (DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat)))
     955    bool fNeedsDropDir = DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat));
     956    LogFlowFunc(("strFormat=%s, uAction=0x%x, fNeedsDropDir=%RTbool\n",
     957                 pcszFormat, uAction, fNeedsDropDir));
     958
     959    DnDGuestResponse *pDnD = d->response();
     960    AssertPtr(pDnD);
     961
     962    if (fNeedsDropDir)
    883963    {
    884964        char szDropDir[RTPATH_MAX];
     
    889969                               szDropDir, rc);
    890970        LogFlowFunc(("Dropped files directory on the host is: %s\n", szDropDir));
     971
     972        pDnD->setDropDir(szDropDir);
    891973    }
    892974
     
    899981        paParms[i++].setUInt32(uAction);
    900982
    901         DnDGuestResponse *pDnD = d->response();
    902 
    903983        /* Reset any old data and the progress status. */
    904984        pDnD->reset();
     
    9251005    const ComObjPtr<Guest> &p = d->p;
    9261006
    927     HRESULT rc = S_OK;
    928 
    929     DnDGuestResponse *pDnD = d->response();
    930     if (pDnD)
     1007    HRESULT hr = S_OK;
     1008
     1009    DnDGuestResponse *pResp = d->response();
     1010    if (pResp)
    9311011    {
    9321012        com::SafeArray<BYTE> sfaData;
    9331013
    934         uint32_t cbData = pDnD->size();
     1014        size_t cbData = pResp->size();
    9351015        if (cbData)
    9361016        {
    937             /* Copy the data into a safe array of bytes. */
    938             const void *pvData = pDnD->data();
    939             if (sfaData.resize(cbData))
    940                 memcpy(sfaData.raw(), pvData, cbData);
     1017            const void *pvData = pResp->data();
     1018            AssertPtr(pvData);
     1019
     1020            Utf8Str strFormat = pResp->format();
     1021            LogFlowFunc(("strFormat=%s, strDropDir=%s\n",
     1022                         strFormat.c_str(), pResp->dropDir().c_str()));
     1023
     1024            if (DnDMIMEHasFileURLs(strFormat.c_str(), strFormat.length()))
     1025            {
     1026                DnDURIList lstURI;
     1027                int rc2 = lstURI.RootFromURIData(pvData, cbData, 0 /* fFlags */);
     1028                if (RT_SUCCESS(rc2))
     1029                {
     1030                    Utf8Str strURIs = lstURI.RootToString(pResp->dropDir());
     1031                    if (sfaData.resize(strURIs.length()))
     1032                        memcpy(sfaData.raw(), strURIs.c_str(), strURIs.length());
     1033                    else
     1034                        hr = E_OUTOFMEMORY;
     1035                }
     1036                else
     1037                    hr = VBOX_E_IPRT_ERROR;
     1038
     1039                LogFlowFunc(("Found %zu root URIs, rc=%Rrc\n", lstURI.RootCount(), rc2));
     1040            }
    9411041            else
    942                 rc = E_OUTOFMEMORY;
     1042            {
     1043                /* Copy the data into a safe array of bytes. */
     1044                if (sfaData.resize(cbData))
     1045                    memcpy(sfaData.raw(), pvData, cbData);
     1046                else
     1047                    hr = E_OUTOFMEMORY;
     1048            }
    9431049        }
    9441050
    945 #ifdef DEBUG_andy
    946         LogFlowFunc(("Received %RU32 bytes\n", cbData));
    947 #endif
     1051        LogFlowFunc(("cbData=%zu\n", cbData));
     1052
    9481053        /* Detach in any case, regardless of data size. */
    9491054        sfaData.detachTo(ComSafeArrayOutArg(data));
    9501055
    9511056        /* Delete the data. */
    952         pDnD->reset();
     1057        pResp->reset();
    9531058    }
    9541059    else
    955         rc = VBOX_E_INVALID_OBJECT_STATE;
    956 
     1060        hr = VBOX_E_INVALID_OBJECT_STATE;
     1061
     1062    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     1063    return hr;
     1064}
     1065
     1066int GuestDnD::onGHSendData(DnDGuestResponse *pResp,
     1067                           const void *pvData, size_t cbData,
     1068                           size_t cbTotalSize)
     1069{
     1070    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
     1071    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
     1072    AssertReturn(cbData, VERR_INVALID_PARAMETER);
     1073    AssertReturn(cbTotalSize, VERR_INVALID_PARAMETER);
     1074
     1075    int rc = pResp->dataAdd(pvData, cbData, NULL /* Current size */);
     1076    if (RT_SUCCESS(rc))
     1077        rc = pResp->dataSetStatus(cbData, cbTotalSize);
     1078
     1079    LogFlowFuncLeaveRC(rc);
    9571080    return rc;
    9581081}
     1082
     1083int GuestDnD::onGHSendDir(DnDGuestResponse *pResp,
     1084                          const char *pszPath, size_t cbPath,
     1085                          uint32_t fMode)
     1086{
     1087    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
     1088    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     1089    AssertReturn(cbPath, VERR_INVALID_PARAMETER);
     1090
     1091    LogFlowFunc(("strDir=%s, cbPath=%zu, fMode=0x%x\n",
     1092                 pszPath, cbPath, fMode));
     1093
     1094    int rc;
     1095    char *pszDir = RTPathJoinA(pResp->dropDir().c_str(), pszPath);
     1096    if (pszDir)
     1097    {
     1098        rc = RTDirCreateFullPath(pszDir, fMode);
     1099        RTStrFree(pszDir);
     1100    }
     1101    else
     1102        rc = VERR_NO_MEMORY;
     1103
     1104    if (RT_SUCCESS(rc))
     1105        rc = pResp->dataSetStatus(cbPath);
     1106
     1107    LogFlowFuncLeaveRC(rc);
     1108    return rc;
     1109}
     1110
     1111int GuestDnD::onGHSendFile(DnDGuestResponse *pResp,
     1112                           const char *pszPath, size_t cbPath,
     1113                           void *pvData, size_t cbData, uint32_t fMode)
     1114{
     1115    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
     1116    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     1117    AssertReturn(cbPath, VERR_INVALID_PARAMETER);
     1118
     1119    LogFlowFunc(("strFile=%s, cbPath=%zu, fMode=0x%x\n",
     1120                 pszPath, cbPath, fMode));
     1121
     1122    /** @todo Add file locking between calls! */
     1123    int rc;
     1124    char *pszFile = RTPathJoinA(pResp->dropDir().c_str(), pszPath);
     1125    if (pszFile)
     1126    {
     1127        RTFILE hFile;
     1128        rc = RTFileOpen(&hFile, pszFile,
     1129                        RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE);
     1130        if (RT_SUCCESS(rc))
     1131        {
     1132            rc = RTFileWrite(hFile, pvData, cbData,
     1133                             NULL /* No partial writes */);
     1134            RTFileClose(hFile);
     1135        }
     1136        RTStrFree(pszFile);
     1137    }
     1138    else
     1139        rc = VERR_NO_MEMORY;
     1140
     1141    if (RT_SUCCESS(rc))
     1142        rc = pResp->dataSetStatus(cbData);
     1143
     1144    LogFlowFuncLeaveRC(rc);
     1145    return rc;
     1146}
    9591147#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
    9601148
    961 DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms)
     1149/* static */
     1150DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function,
     1151                                                        void *pvParms, uint32_t cbParms)
    9621152{
    9631153    LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n",
     
    9671157    if (!pGuest->m_pGuestDnD)
    9681158        return VINF_SUCCESS;
     1159
     1160    GuestDnD *pGuestDnD = pGuest->m_pGuestDnD;
     1161    AssertPtr(pGuestDnD);
    9691162
    9701163    GuestDnDPrivate *d = static_cast<GuestDnDPrivate*>(pGuest->m_pGuestDnD->d_ptr);
     
    9841177            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGACKOPDATA) == cbParms, VERR_INVALID_PARAMETER);
    9851178            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1179
    9861180            pResp->setDefAction(pCBData->uAction);
     1181
    9871182            rc = pResp->notifyAboutGuestResponse();
    9881183            break;
     
    9951190            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGREQDATADATA) == cbParms, VERR_INVALID_PARAMETER);
    9961191            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1192
    9971193            pResp->setFormat(pCBData->pszFormat);
     1194
    9981195            rc = pResp->notifyAboutGuestResponse();
    9991196            break;
     
    10061203            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA) == cbParms, VERR_INVALID_PARAMETER);
    10071204            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1205
    10081206            rc = pResp->setProgress(pCBData->uPercentage, pCBData->uState, pCBData->rc);
    10091207            break;
     
    10171215            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA) == cbParms, VERR_INVALID_PARAMETER);
    10181216            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1217
    10191218            pResp->setFormat(pCBData->pszFormat);
    10201219            pResp->setDefAction(pCBData->uDefAction);
    10211220            pResp->setAllActions(pCBData->uAllActions);
     1221
    10221222            rc = pResp->notifyAboutGuestResponse();
    10231223            break;
     
    10311231            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    10321232
    1033             uint32_t cbCurSize = 0;
    1034             rc = pResp->dataAdd(pCBData->pvData, pCBData->cbData, &cbCurSize);
    1035             if (RT_SUCCESS(rc))
    1036             {
    1037                 /** @todo Store pCBData->cbAllSize in the guest's response struct
    1038                  *        if not set already. */
    1039                 uint32_t cbTotalSize = pCBData->cbAllSize;
    1040                 unsigned int cPercentage;
    1041                 if (!cbTotalSize) /* Watch out for division by zero. */
    1042                     cPercentage = 100;
    1043                 else
    1044                     cPercentage = cbCurSize * 100.0 / cbTotalSize;
    1045 
    1046                 /** @todo Don't use anonymous enums. */
    1047                 uint32_t uState = DragAndDropSvc::DND_PROGRESS_RUNNING;
    1048                 if (   cbTotalSize == cbCurSize
    1049                     /* Empty data? Should not happen, but anyway ... */
    1050                     || !cbTotalSize)
    1051                 {
    1052                     uState = DragAndDropSvc::DND_PROGRESS_COMPLETE;
    1053                 }
    1054 
    1055                 rc = pResp->setProgress(cPercentage, uState);
    1056             }
    1057 
    1058             /** @todo For now we instantly confirm the cancel. Check if the
    1059              *        guest should first clean up stuff itself and than really confirm
    1060              *        the cancel request by an extra message. */
    1061             if (rc == VERR_CANCELLED)
    1062                 pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED);
     1233            rc = pGuestDnD->onGHSendData(pResp, pCBData->pvData, pCBData->cbData,
     1234                                         pCBData->cbTotalSize);
     1235            break;
     1236        }
     1237
     1238        case DragAndDropSvc::GUEST_DND_GH_SND_DIR:
     1239        {
     1240            DragAndDropSvc::PVBOXDNDCBSNDDIRDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDIRDATA>(pvParms);
     1241            AssertPtr(pCBData);
     1242            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDIRDATA) == cbParms, VERR_INVALID_PARAMETER);
     1243            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1244
     1245            rc = pGuestDnD->onGHSendDir(pResp, pCBData->pszPath, pCBData->cbPath, pCBData->fMode);
     1246            break;
     1247        }
     1248
     1249        case DragAndDropSvc::GUEST_DND_GH_SND_FILE:
     1250        {
     1251            DragAndDropSvc::PVBOXDNDCBSNDFILEDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDFILEDATA>(pvParms);
     1252            AssertPtr(pCBData);
     1253            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDFILEDATA) == cbParms, VERR_INVALID_PARAMETER);
     1254            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
     1255
     1256            rc = pGuestDnD->onGHSendFile(pResp, pCBData->pszFilePath, pCBData->cbFilePath,
     1257                                         pCBData->pvData, pCBData->cbData, pCBData->fMode);
    10631258            break;
    10641259        }
     
    10711266            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
    10721267
    1073             /* Cleanup */
     1268            /* Cleanup. */
    10741269            pResp->reset();
    10751270            rc = pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc);
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