VirtualBox

Changeset 50460 in vbox


Ignore:
Timestamp:
Feb 14, 2014 9:46:58 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
92295
Message:

DnD: Update.

Location:
trunk
Files:
15 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/DragAndDropSvc.h

    r50305 r50460  
    9797    /** The host informs the guest that a DnD drop operation
    9898     *  has been started and that the host wants the data in
    99      *  a specific mime-type. */
     99     *  a specific MIME type. */
    100100    HOST_DND_GH_EVT_DROPPED,
    101101
     
    134134     */
    135135    GUEST_DND_GH_ACK_PENDING           = 500,
     136    /**
     137     * Sends data of the requsted MIME type to the host. There can
     138     * be more than one message if the actual data does not fit
     139     * into one.
     140     */
    136141    GUEST_DND_GH_SND_DATA,
    137142    GUEST_DND_GH_EVT_ERROR,
  • trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk

    r50101 r50460  
    5151        VBoxDnDDropSource.cpp \
    5252        VBoxDnDDropTarget.cpp
     53 VBoxTray_LIBS     += \
     54        $(PATH_STAGE_LIB)/additions/VBoxDnDGuestR3Lib$(VBOX_SUFF_LIB)
    5355endif
    5456ifdef VBOX_WITH_GUEST_PROPS
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp

    r50399 r50460  
    14021402
    14031403        rc = VbglR3DnDProcessNextMessage(uClientID, &pEvent->Event);
    1404         LogFlowFunc(("VbglR3DnDProcessNextMessage returned rc=%Rrc\n", rc));
     1404        LogFlowFunc(("VbglR3DnDProcessNextMessage returned uType=%RU32, rc=%Rrc\n",
     1405                     pEvent->Event.uType, rc));
    14051406
    14061407        if (ASMAtomicReadBool(&pCtx->fShutdown))
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp

    r50101 r50460  
    2727#include "VBoxDnD.h"
    2828
     29#ifdef DEBUG
     30 /* Enable the following line to get much more debug output about
     31  * (un)known clipboard formats. */
     32 //#define VBOX_DND_DEBUG_FORMATS
     33#endif
     34
    2935/** @todo Implement IDataObjectAsyncCapability interface? */
    3036
     
    188194    AssertPtrReturn(pMedium, DV_E_FORMATETC);
    189195
    190     LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium));
    191 
    192196    ULONG lIndex;
    193197    if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
     
    195199    if (lIndex >= mcFormats) /* Paranoia. */
    196200        return DV_E_FORMATETC;
     201
     202    LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium));
    197203
    198204    FORMATETC *pThisFormat = &mpFormatEtc[lIndex];
     
    474480const char* VBoxDnDDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
    475481{
     482#ifdef VBOX_DND_DEBUG_FORMATS
    476483    char szFormat[128];
    477484    if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
    478485        LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat));
     486#endif
    479487
    480488    switch (fmt)
     
    572580    }
    573581
     582#ifdef VBOX_DND_DEBUG_FORMATS
    574583    LogFlowFunc(("Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n",
    575584                 pFormatEtc->tymed, pFormatEtc->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
    576585                 pFormatEtc->dwAspect));
    577 
     586#endif
    578587    return false;
    579588}
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp

    r50305 r50460  
    3939
    4040#include "VBGLR3Internal.h"
     41#include "VBox/GuestHost/DragAndDrop.h"
    4142#include "VBox/HostServices/DragAndDropSvc.h"
    4243
     
    4748 * Todo:
    4849 * - Sending dirs/files in the G->H case
    49  * - Maybe the EOL converting of text mime-types (not fully sure, eventually
     50 * - Maybe the EOL converting of text MIME types (not fully sure, eventually
    5051 *   better done on the host side)
    5152 */
    52 
    53 static int vbglR3DnDPathSanitize(char *pszPath, size_t cbPath);
    5453
    5554/******************************************************************************
    5655 *    Private internal functions                                              *
    5756 ******************************************************************************/
    58 
    59 static int vbglR3DnDCreateDropDir(char* pszDropDir, size_t cbSize)
    60 {
    61     AssertPtrReturn(pszDropDir, VERR_INVALID_POINTER);
    62     AssertReturn(cbSize,        VERR_INVALID_PARAMETER);
    63 
    64     /** @todo On Windows we also could use the registry to override
    65      *        this path, on Posix a dotfile and/or a guest property
    66      *        can be used. */
    67 
    68     /* Get the users temp directory. Don't use the user's root directory (or
    69      * something inside it) because we don't know for how long/if the data will
    70      * be kept after the guest OS used it. */
    71     int rc = RTPathTemp(pszDropDir, cbSize);
    72     if (RT_FAILURE(rc))
    73         return rc;
    74 
    75     /* Append our base drop directory. */
    76     rc = RTPathAppend(pszDropDir, cbSize, "VirtualBox Dropped Files");
    77     if (RT_FAILURE(rc))
    78         return rc;
    79 
    80     /* Create it when necessary. */
    81     if (!RTDirExists(pszDropDir))
    82     {
    83         rc = RTDirCreateFullPath(pszDropDir, RTFS_UNIX_IRWXU);
    84         if (RT_FAILURE(rc))
    85             return rc;
    86     }
    87 
    88     /* The actually drop directory consist of the current time stamp and a
    89      * unique number when necessary. */
    90     char pszTime[64];
    91     RTTIMESPEC time;
    92     if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))
    93         return VERR_BUFFER_OVERFLOW;
    94     rc = vbglR3DnDPathSanitize(pszTime, sizeof(pszTime));
    95     if (RT_FAILURE(rc))
    96         return rc;
    97 
    98     rc = RTPathAppend(pszDropDir, cbSize, pszTime);
    99     if (RT_FAILURE(rc))
    100         return rc;
    101 
    102     /* Create it (only accessible by the current user) */
    103     return RTDirCreateUniqueNumbered(pszDropDir, cbSize, RTFS_UNIX_IRWXU, 3, '-');
    104 }
    10557
    10658static int vbglR3DnDQueryNextHostMessageType(uint32_t uClientId, uint32_t *puMsg, uint32_t *pcParms, bool fWait)
     
    319271    AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER);
    320272
     273    if (!*pcbDataRecv)
     274        return VERR_INVALID_PARAMETER;
     275
    321276    /* Make a string list out of the uri data. */
    322     RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n");
     277    RTCList<RTCString> uriList =
     278        RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n");
    323279    if (uriList.isEmpty())
    324280        return VINF_SUCCESS;
     
    331287    /* Create and query the (unique) drop target directory. */
    332288    char pszDropDir[RTPATH_MAX];
    333     int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir));
     289    int rc = DnDDirCreateDroppedFiles(pszDropDir, sizeof(pszDropDir));
    334290    if (RT_FAILURE(rc))
    335291    {
     
    349305        if (pszFilePath)
    350306        {
    351             rc = vbglR3DnDPathSanitize(pszFilePath, strlen(pszFilePath));
     307            rc = DnDPathSanitize(pszFilePath, strlen(pszFilePath));
    352308            if (RT_FAILURE(rc))
    353309                break;
    354310
    355311            /** @todo Use RTPathJoin? */
    356             RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath);
     312            RTCString strFullPath
     313                = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath);
    357314            char *pszNewUri = RTUriFileCreate(strFullPath.c_str());
    358315            if (pszNewUri)
     
    376333    }
    377334
    378     /* Lists for holding created files & directories in the case of a
    379      * rollback. */
     335    /* Lists for holding created files & directories
     336     * in the case of a rollback. */
    380337    RTCList<RTCString> guestDirList;
    381338    RTCList<RTCString> guestFileList;
    382     char pszPathname[RTPATH_MAX];
     339    char pszPathName[RTPATH_MAX];
    383340    uint32_t cbPathname = 0;
    384341    bool fLoop = RT_SUCCESS(rc); /* No error occurred yet? */
     
    396353                    uint32_t fMode = 0;
    397354                    rc = vbglR3DnDHGProcessSendDirMessage(uClientId,
    398                                                           pszPathname,
    399                                                           sizeof(pszPathname),
     355                                                          pszPathName,
     356                                                          sizeof(pszPathName),
    400357                                                          &cbPathname,
    401358                                                          &fMode);
    402359                    if (RT_SUCCESS(rc))
    403                         rc = vbglR3DnDPathSanitize(pszPathname, sizeof(pszPathname));
     360                        rc = DnDPathSanitize(pszPathName, sizeof(pszPathName));
    404361                    if (RT_SUCCESS(rc))
    405362                    {
    406                         char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname);
     363                        char *pszNewDir = RTPathJoinA(pszDropDir, pszPathName);
    407364                        if (pszNewDir)
    408365                        {
     
    423380                    uint32_t fMode = 0;
    424381                    rc = vbglR3DnDHGProcessSendFileMessage(uClientId,
    425                                                            pszPathname,
    426                                                            sizeof(pszPathname),
     382                                                           pszPathName,
     383                                                           sizeof(pszPathName),
    427384                                                           &cbPathname,
    428385                                                           pvTmpData,
     
    431388                                                           &fMode);
    432389                    if (RT_SUCCESS(rc))
    433                         rc = vbglR3DnDPathSanitize(pszPathname, sizeof(pszPathname));
     390                        rc = DnDPathSanitize(pszPathName, sizeof(pszPathName));
    434391                    if (RT_SUCCESS(rc))
    435392                    {
    436                         char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname);
     393                        char *pszNewFile = RTPathJoinA(pszDropDir, pszPathName);
    437394                        if (pszNewFile)
    438395                        {
     
    666623    {
    667624        /* Check if this is an URI event. If so, let VbglR3 do all the actual
    668          * data transfer + file /directory creation internally without letting
     625         * data transfer + file/directory creation internally without letting
    669626         * the caller know.
    670627         *
     
    747704    }
    748705
    749     return rc;
    750 }
    751 
    752 static int vbglR3DnDPathSanitize(char *pszPath, size_t cbPath)
    753 {
    754     int rc = VINF_SUCCESS;
    755 #ifdef RT_OS_WINDOWS
    756     /* Filter out characters not allowed on Windows platforms, put in by
    757        RTTimeSpecToString(). */
    758     /** @todo Use something like RTPathSanitize() when available. Later. */
    759     RTUNICP aCpSet[] =
    760         { ' ', ' ', '(', ')', '-', '.', '0', '9', 'A', 'Z', 'a', 'z', '_', '_',
    761           0xa0, 0xd7af, '\0' };
    762     ssize_t cReplaced = RTStrPurgeComplementSet(pszPath, aCpSet, '_' /* Replacement */);
    763     if (cReplaced < 0)
    764         rc = VERR_INVALID_UTF8_ENCODING;
    765 #endif
    766706    return rc;
    767707}
     
    886826                break;
    887827            }
     828#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    888829            case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
    889830            {
     
    908849                break;
    909850            }
     851#endif
    910852            default:
     853            {
     854                pEvent->uType = uMsg;
     855
    911856                rc = VERR_NOT_SUPPORTED;
    912857                break;
     858            }
    913859        }
    914860    }
     
    979925}
    980926
    981 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, void *pvData, uint32_t cbData)
     927VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId,
     928                                    void *pvData, uint32_t cbData)
    982929{
    983930    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
     
    993940
    994941    int rc          = VINF_SUCCESS;
    995     uint32_t cbMax  = _1M; /** @todo Remove 1 MB limit. */
     942    uint32_t cbMax  = _64K; /* Transfer max. 64K chunks per message. */
    996943    uint32_t cbSent = 0;
    997944
    998945    while (cbSent < cbData)
    999946    {
    1000         /* Initialize parameter */
    1001947        uint32_t cbToSend = RT_MIN(cbData - cbSent, cbMax);
    1002948        Msg.pData.SetPtr(static_cast<uint8_t*>(pvData) + cbSent, cbToSend);
    1003         /* Do request */
     949
    1004950        rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
    1005951        if (RT_SUCCESS(rc))
    1006         {
    1007952            rc = Msg.hdr.result;
    1008             /* Did the host cancel the event? */
    1009             if (rc == VERR_CANCELLED)
    1010                 break;
    1011         }
    1012         else
     953
     954        if (RT_FAILURE(rc))
    1013955            break;
     956
    1014957        cbSent += cbToSend;
    1015 //        RTThreadSleep(500);
    1016     }
     958    }
     959
     960    if (RT_SUCCESS(rc))
     961        Assert(cbSent == cbData);
    1017962
    1018963    return rc;
  • trunk/src/VBox/Additions/x11/VBoxClient/Makefile.kmk

    r50338 r50460  
    7575 VBoxClient_SOURCES += \
    7676        draganddrop.cpp
     77 VBoxClient_LIBS     += \
     78        $(PATH_STAGE_LIB)/additions/VBoxDnDGuestR3Lib$(VBOX_SUFF_LIB)
    7779endif
    7880
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r50305 r50460  
    455455 ifdef VBOX_WITH_DRAG_AND_DROP_GH
    456456  VirtualBox_QT_MOCHDRS += \
    457         src/runtime/UIDnDMIMEData.h
     457        src/runtime/UIDnDMIMEData.h \
     458        src/runtime/UIDnDDrag.h
    458459 endif
    459460endif
     
    492493
    493494ifdef VBOX_WITH_DRAG_AND_DROP
     495 VirtualBox_QT_MOCSRCS += \
     496        src/runtime/UIDnDHandler.cpp
    494497 ifdef VBOX_WITH_DRAG_AND_DROP_GH
    495498  VirtualBox_QT_MOCSRCS += \
     499        src/runtime/UIDnDDrag.cpp \
    496500        src/runtime/UIDnDMIMEData.cpp
    497501 endif
     
    781785 ifdef VBOX_WITH_DRAG_AND_DROP_GH
    782786  VirtualBox_SOURCES += \
    783         src/runtime/UIDnDMIMEData.cpp
    784   VirtualBox_QT_MOCSRCS += \
    785         src/runtime/UIDnDMIMEData.cpp
     787        src/runtime/UIDnDMIMEData.cpp \
     788        src/runtime/UIDnDDrag.cpp
     789  VirtualBox_SOURCES.win += \
     790        src/runtime/UIDnDDropSource_win.cpp \
     791        src/runtime/UIDnDDataObject_win.cpp \
     792        src/runtime/UIDnDEnumFormat_win.cpp
    786793 endif
    787794endif
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp

    r50306 r50460  
    3434#include "UIDnDHandler.h"
    3535#ifdef VBOX_WITH_DRAG_AND_DROP_GH
    36 # include "UIDnDMIMEData.h"
     36# include "UIDnDDrag.h"
    3737#endif
    3838#include "UIMessageCenter.h"
     
    4646
    4747UIDnDHandler::UIDnDHandler(void)
    48 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    49     : pMData(NULL)
    50 #endif
     48    : mMode(Unknown)
    5149{
    5250}
     
    6058                                         const QMimeData *pMimeData, QWidget * /* pParent = NULL */)
    6159{
     60    if (mMode == GH) /* Wrong mode? Bail out. */
     61        return Qt::IgnoreAction;
     62
    6263    LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
    6364                 screenId, x, y, toVBoxDnDAction(proposedAction)));
     
    7879                                        const QMimeData *pMimeData, QWidget * /* pParent = NULL */)
    7980{
     81    if (mMode == GH) /* Wrong mode? Bail out. */
     82        return Qt::IgnoreAction;
     83
    8084#ifdef DEBUG_andy
    8185    LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
     
    99103                                        const QMimeData *pMimeData, QWidget *pParent /* = NULL */)
    100104{
     105    if (mMode == GH) /* Wrong mode? Bail out. */
     106        return Qt::IgnoreAction;
     107
    101108    LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
    102109                 screenId, x, y, toVBoxDnDAction(proposedAction)));
     
    114121    if (result != KDragAndDropAction_Ignore)
    115122    {
    116         /* Get the actually data */
     123        /* Get the actual MIME data in the requested format. */
    117124        const QByteArray &d = pMimeData->data(format);
    118125        if (   !d.isEmpty()
    119126            && !format.isEmpty())
    120127        {
    121             /* We need the data in the vector format. */
     128            /* Convert the actual MIME data to a vector (needed
     129             * for the COM wrapper). */
    122130            QVector<uint8_t> dv(d.size());
    123131            memcpy(dv.data(), d.constData(), d.size());
     
    126134            if (guest.isOk())
    127135            {
    128                 msgCenter().showModalProgressDialog(progress, tr("Dropping data ..."), ":/progress_dnd_hg_90px.png", pParent);
    129                 if (!progress.GetCanceled() && (!progress.isOk() || progress.GetResultCode() != 0))
     136                msgCenter().showModalProgressDialog(progress,
     137                                                    tr("Dropping data ..."), ":/progress_dnd_hg_90px.png",
     138                                                    pParent);
     139                if (   !progress.GetCanceled()
     140                    && (   !progress.isOk()
     141                        ||  progress.GetResultCode() != 0))
    130142                {
    131143                    msgCenter().cannotDropData(progress, pParent);
     
    146158void UIDnDHandler::dragHGLeave(CGuest &guest, ulong screenId, QWidget * /* pParent = NULL */)
    147159{
     160    if (mMode == GH) /* Wrong mode? Bail out. */
     161        return;
     162
    148163    LogFlowFunc(("screenId=%RU32\n", screenId));
    149164    guest.DragHGLeave(screenId);
     
    154169    int rc;
    155170#ifdef VBOX_WITH_DRAG_AND_DROP_GH
     171    if (mMode == HG) /* Wrong mode? Bail out. */
     172        return VERR_WRONG_ORDER;
     173
    156174    /*
    157175     * How this works: Host is asking the guest if there is any DnD
     
    169187    LogFlowFunc(("defaultAction=%d, numFormats=%d\n", defaultAction, vecFmtGuest.size()));
    170188
    171     /*
    172      * Do guest -> host format conversion, if needed.
    173      * On X11 this already maps to the Xdnd protocol.
    174      ** @todo What about the MacOS Carbon Drag Manager? Needs testing.
    175      *
    176      * See: https://www.iana.org/assignments/media-types/media-types.xhtml
    177      */
    178     LogFlowFunc(("Number of guest formats: %d\n", vecFmtGuest.size()));
    179189    QStringList lstFmtNative;
    180     for (int i = 0; i < vecFmtGuest.size(); i++)
     190    if (defaultAction != KDragAndDropAction_Ignore)
    181191    {
    182         const QString &strFmtGuest = vecFmtGuest.at(i);
    183         LogFlowFunc(("\tFormat %d: %s\n", i,
    184                      strFmtGuest.toAscii().constData()));
     192        /*
     193         * Do guest -> host format conversion, if needed.
     194         * On X11 this already maps to the Xdnd protocol.
     195         ** @todo What about the MacOS Carbon Drag Manager? Needs testing.
     196         *
     197         * See: https://www.iana.org/assignments/media-types/media-types.xhtml
     198         */
     199        LogFlowFunc(("Number of guest formats: %d\n", vecFmtGuest.size()));
     200        for (int i = 0; i < vecFmtGuest.size(); i++)
     201        {
     202            const QString &strFmtGuest = vecFmtGuest.at(i);
     203            LogFlowFunc(("\tFormat %d: %s\n", i,
     204                         strFmtGuest.toAscii().constData()));
    185205# ifdef RT_OS_WINDOWS
    186         /* CF_TEXT */
    187         if (   strFmtGuest.contains("text/plain", Qt::CaseInsensitive)
    188             && !lstFmtNative.contains("text/plain"))
    189         {
    190             lstFmtNative << "text/plain";
    191         }
    192         /* CF_HDROP */
    193         else if (   strFmtGuest.contains("text/uri-list", Qt::CaseInsensitive)
    194                  && !lstFmtNative.contains("text/uri-list"))
    195         {
    196             lstFmtNative << "text/uri-list";
    197         }
     206            /* CF_TEXT */
     207            if (   strFmtGuest.contains("text/plain", Qt::CaseInsensitive)
     208                && !lstFmtNative.contains("text/plain"))
     209            {
     210                lstFmtNative << "text/plain";
     211            }
     212            /* CF_HDROP */
     213            else if (   strFmtGuest.contains("text/uri-list", Qt::CaseInsensitive)
     214                     && !lstFmtNative.contains("text/uri-list"))
     215            {
     216                lstFmtNative << "text/uri-list";
     217            }
    198218# else
    199         /* On non-Windows just do a 1:1 mapping. */
    200         lstFmtNative << strFmtGuest;
     219            /* On non-Windows just do a 1:1 mapping. */
     220            lstFmtNative << strFmtGuest;
    201221#  ifdef RT_OS_MACOS
    202         /** @todo Does the mapping apply here? Don't think so ... */
     222            /** @todo Does the mapping apply here? Don't think so ... */
    203223#  endif
    204224# endif /* !RT_OS_WINDOWS */
     225        }
     226
     227        LogFlowFunc(("Number of native formats: %d\n", lstFmtNative.size()));
     228# ifdef DEBUG
     229        for (int i = 0; i < lstFmtNative.size(); i++)
     230            LogFlowFunc(("\tFormat %d: %s\n", i, lstFmtNative.at(i).toAscii().constData()));
     231# endif
    205232    }
    206233
    207     LogFlowFunc(("Number of native formats: %d\n", lstFmtNative.size()));
    208 # ifdef DEBUG
    209     for (int i = 0; i < lstFmtNative.size(); i++)
    210         LogFlowFunc(("\tFormat %d: %s\n", i, lstFmtNative.at(i).toAscii().constData()));
    211 # endif
    212 
    213     if (    defaultAction != KDragAndDropAction_Ignore
    214         && !lstFmtNative.isEmpty())
     234    if (!lstFmtNative.isEmpty())
    215235    {
    216236        try
    217237        {
    218             QDrag *pDrag = new QDrag(pParent);
    219 
    220             /* pMData is transfered to the QDrag object, so no need for deletion. */
    221             pMData = new UIDnDMimeData(session, lstFmtNative,
    222                                                       toQtDnDAction(defaultAction),
    223                                                       toQtDnDActions(vecActions), pParent);
    224 
    225             /* Inform this object that MIME data from the guest is available so that
    226              * it can update the MIME data object accordingly. */
    227             connect(pMData, SIGNAL(sigDataAvailable(QString)),
    228                     this, SLOT(sltDataAvailable(QString)), Qt::DirectConnection);
    229 
    230             /* Inform the MIME data object of any changes in the current action. */
    231             connect(pDrag, SIGNAL(actionChanged(Qt::DropAction)),
    232                     pMData, SLOT(sltDropActionChanged(Qt::DropAction)));
    233 
    234             /* Fire it up.
    235              *
    236              * On Windows this will start a modal operation using OLE's
    237              * DoDragDrop() method, so this call will block until the DnD operation
    238              * is finished. */
    239             pDrag->setMimeData(pMData);
    240             Qt::DropAction dropAction =
    241                  pDrag->exec(toQtDnDActions(vecActions), toQtDnDAction(defaultAction));
    242             LogFlowFunc(("dropAction=%ld\n", toVBoxDnDAction(dropAction)));
    243 # ifdef RT_OS_WINDOWS
    244             /* Since the QDrag::exec() call above was blocking on Windows, decide what
    245              * to do now, e.g. if there was a "drop" action.
    246              *
    247              * Note: The UIDnDMimeData object will not be not accessible here anymore,
    248              *       since QDrag had its ownership and deleted it after the (blocking)
    249              *       QDrag::exec() call. */
    250 # endif
    251             rc = VINF_SUCCESS;
     238            UIDnDDrag *pDrag = new UIDnDDrag(session, lstFmtNative,
     239                                             toQtDnDAction(defaultAction),
     240                                             toQtDnDActions(vecActions), pParent);
     241            rc = pDrag->DoDragDrop();
     242
     243            delete pDrag;
    252244        }
    253245        catch (std::bad_alloc)
     
    258250    else
    259251        rc = VINF_SUCCESS;
    260 #else
     252#else /* !VBOX_WITH_DRAG_AND_DROP_GH */
    261253    NOREF(session);
    262254    NOREF(screenId);
     
    274266 */
    275267
     268/* static */
    276269KDragAndDropAction UIDnDHandler::toVBoxDnDAction(Qt::DropAction action)
    277270{
     
    286279}
    287280
     281/* static */
    288282QVector<KDragAndDropAction> UIDnDHandler::toVBoxDnDActions(Qt::DropActions actions)
    289283{
     
    301295}
    302296
     297/* static */
    303298Qt::DropAction UIDnDHandler::toQtDnDAction(KDragAndDropAction action)
    304299{
     
    315310}
    316311
     312/* static */
    317313Qt::DropActions UIDnDHandler::toQtDnDActions(const QVector<KDragAndDropAction> &vecActions)
    318314{
     
    343339}
    344340
    345 void UIDnDHandler::sltDataAvailable(const QString &mimeType)
    346 {
    347 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    348     LogFlowFunc(("pMData=0x%p, mimeType=%s\n",
    349                  pMData, mimeType.toAscii().constData()));
    350 
    351     if (pMData)
    352         pMData->setData(mimeType);
    353 #endif
    354 }
    355 
    356341#include "UIDnDHandler.moc"
    357342
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h

    r50306 r50460  
    3535
    3636public:
     37
    3738    /* Singleton factory. */
    3839    static UIDnDHandler* instance(void)
     
    4243        return m_pInstance;
    4344    }
     45
    4446    static void destroy(void)
    4547    {
     
    5052        }
    5153    }
     54
     55    /**
     56     * Current operation mode.
     57     */
     58    enum Mode
     59    {
     60        /** Unknown mode. */
     61        Unknown = 0,
     62        /** Host to guest. */
     63        HG,
     64        /** Guest to host. */
     65        GH
     66    };
    5267
    5368    /* Host -> Guest. */
     
    6075    int            dragGHPending(CSession &session, ulong screenId, QWidget *pParent = NULL);
    6176
    62 public slots:
     77public:
    6378
    64     void sltDataAvailable(const QString &mimetype);
     79    static KDragAndDropAction          toVBoxDnDAction(Qt::DropAction action);
     80    static QVector<KDragAndDropAction> toVBoxDnDActions(Qt::DropActions actions);
     81    static Qt::DropAction              toQtDnDAction(KDragAndDropAction action);
     82    static Qt::DropActions             toQtDnDActions(const QVector<KDragAndDropAction> &vecActions);
    6583
    6684private:
     
    7088    virtual ~UIDnDHandler(void) {}
    7189
    72     /* Private helpers. */
    73     static KDragAndDropAction          toVBoxDnDAction(Qt::DropAction action);
    74     static QVector<KDragAndDropAction> toVBoxDnDActions(Qt::DropActions actions);
    75     static Qt::DropAction              toQtDnDAction(KDragAndDropAction action);
    76     static Qt::DropActions             toQtDnDActions(const QVector<KDragAndDropAction> &vecActions);
    77 
    78 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    79     UIDnDMimeData *pMData;
    80     friend class UIDnDMimeData;
    81 #endif
     90    /** The current operation mode. */
     91    Mode mMode;
    8292};
    8393
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp

    r50305 r50460  
    2020/* Qt includes: */
    2121#include <QApplication>
     22#include <QFileInfo>
    2223#include <QKeyEvent>
    2324#include <QMimeData>
     
    3435/* GUI includes: */
    3536#include "UIDnDMIMEData.h"
     37#include "UIDnDDrag.h"
    3638#include "UIMessageCenter.h"
    3739
    3840UIDnDMimeData::UIDnDMimeData(CSession &session, QStringList formats,
    3941                             Qt::DropAction defAction, Qt::DropActions actions,
    40                              QWidget *pParent)
     42                             UIDnDDrag *pParent)
    4143    : m_pParent(pParent)
    4244    , m_session(session)
     
    9698}
    9799
    98 bool UIDnDMimeData::hasFormat(const QString &mimeType) const
    99 {
    100     bool fRc = m_lstFormats.contains(mimeType);
     100bool UIDnDMimeData::hasFormat(const QString &strMIMEType) const
     101{
     102    bool fRc = m_lstFormats.contains(strMIMEType);
    101103    LogFlowFunc(("%s: %RTbool (QtMimeData: %RTbool)\n",
    102                  mimeType.toStdString().c_str(),
    103                  fRc, QMimeData::hasFormat(mimeType)));
     104                 strMIMEType.toStdString().c_str(),
     105                 fRc, QMimeData::hasFormat(strMIMEType)));
    104106    return fRc;
    105107}
    106108
    107 QVariant UIDnDMimeData::retrieveData(const QString &mimeType,
     109QVariant UIDnDMimeData::retrieveData(const QString &strMIMEType,
    108110                                     QVariant::Type type) const
    109111{
    110112    LogFlowFunc(("m_enmState=%d, mimeType=%s, type=%d (%s)\n",
    111                  m_enmState, mimeType.toStdString().c_str(),
     113                 m_enmState, strMIMEType.toStdString().c_str(),
    112114                 type, QVariant::typeToName(type)));
    113115
    114116    bool fCanDrop = true;
    115117
    116 #if 0
    117118#ifdef RT_OS_WINDOWS
    118     Qt::MouseButtons mouseBtns = Qt::NoButton;
    119     bool fLeftBtnDown = RT_BOOL(GetAsyncKeyState(VK_LBUTTON) & 0x8000);
    120     if (fLeftBtnDown)
    121         mouseBtns |= Qt::LeftButton;
    122 # ifdef DEBUG_andy
    123     LogFlowFunc(("mouseButtons=0x%x, GetAsyncKeyState(VK_LBUTTON)=%RTbool\n",
    124                  mouseBtns, fLeftBtnDown));
    125 # endif
    126     if (mouseBtns == Qt::NoButton)
    127         m_enmState = Dropped;
    128 #endif
    129 #endif
    130 
    131 #ifdef RT_OS_WINDOWS
    132     /* On Windows we only will get into this function if OLE's DoDragDrop
    133      * routine (called by QtDrag) decides that a drop event just happened.
    134      * So just update our internal state to reflect the same as on other
    135      * platforms. */
     119    /* On Windows this function will be called several times by Qt's
     120     * OLE-specific internals to figure out which data formats we have
     121     * to offer. So just assume we can drop data here for a start.* */
    136122    fCanDrop = true;
    137123#else
    138     /* Mouse button released? See eventFilter for more information. */
     124    /* On non-Windows our state gets updated via an own event filter
     125     * (see UIDnDMimeData::eventFilter). This filter will update the current
     126     * operation state for us (based on the mouse buttons). */
    139127    if (m_enmState != Dropped)
    140128        fCanDrop = false;
     
    143131    /* Do we support the requested MIME type? */
    144132    if (   fCanDrop
    145         && !m_lstFormats.contains(mimeType))
     133        && !m_lstFormats.contains(strMIMEType))
    146134    {
    147135        LogFlowFunc(("Unsupported MIME type=%s\n",
    148                      mimeType.toStdString().c_str()));
     136                     strMIMEType.toStdString().c_str()));
    149137        fCanDrop = false;
    150138    }
     
    169157        LogFlowFunc(("Skipping request, m_enmState=%d ...\n",
    170158                     m_enmState));
    171         return QMimeData::retrieveData(mimeType, type);
    172     }
    173 
    174     if (m_enmState == Dragging)
    175     {
    176         int rc = VINF_SUCCESS;
    177 
    178         CGuest guest = m_session.GetConsole().GetGuest();
    179         /* Start getting the data from the guest. First inform the guest we
    180          * want the data in the specified MIME type. */
    181         CProgress progress = guest.DragGHDropped(mimeType,
    182                                                  UIDnDHandler::toVBoxDnDAction(m_defAction));
    183         if (guest.isOk())
    184         {
    185             msgCenter().showModalProgressDialog(progress,
    186                                                 tr("Retrieving data ..."), ":/progress_dnd_gh_90px.png",
    187                                                 m_pParent);
    188             if (!progress.GetCanceled())
    189             {
    190                 if (   progress.isOk()
    191                     && progress.GetResultCode() == 0)
    192                 {
    193                     /** @todo What about retrieving bigger files? Loop? */
    194 
    195                     /* After the data successfully arrived from the guest, we query it from Main. */
    196                     QVector<uint8_t> data = guest.DragGHGetData();
    197                     if (!data.isEmpty())
    198                     {
    199                         switch (type)
    200                         {
    201                             case QVariant::String:
    202                             {
    203                                 m_data = QVariant(QString(reinterpret_cast<const char*>(data.data())));
    204                                 break;
    205                             }
    206 
    207                             case QVariant::ByteArray:
    208                             {
    209                                 QByteArray ba(reinterpret_cast<const char*>(data.constData()), data.size());
    210                                 m_data = QVariant(ba);
    211                                 break;
    212                             }
    213 
    214                             case QVariant::List:
    215                             {
    216                                 QString strData = QString(reinterpret_cast<const char*>(data.data()));
    217                                 QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts);
    218 
    219                                 m_data = QVariant(lstString);
    220                                 break;
    221                             }
    222 
    223                             default:
    224                                 AssertMsgFailed(("Should never happen, d'oh!\n"));
    225                                 rc = VERR_NOT_SUPPORTED;
    226                                 break;
    227                         }
    228                     }
    229                     /** @todo How often to retry on empty data received? */
    230 
    231                     if (RT_SUCCESS(rc))
    232                         emit sigDataAvailable(mimeType);
    233 
    234                     m_enmState = DataRetrieved;
    235                 }
    236                 else
    237                     msgCenter().cannotDropData(progress, m_pParent);
    238             }
    239             else
    240                 m_enmState = Canceled;
     159        return QMimeData::retrieveData(strMIMEType, type);
     160    }
     161
     162    int rc = VINF_SUCCESS;
     163    if (m_enmState == Dropped)
     164    {
     165        AssertPtr(m_pParent);
     166        rc = m_pParent->RetrieveData(strMIMEType, type, m_data);
     167        if (RT_SUCCESS(rc))
     168        {
     169            /* Tell ourselves that data became available. */
     170            emit sigDataAvailable(strMIMEType);
    241171        }
    242172        else
    243             msgCenter().cannotDropData(guest, m_pParent);
    244     }
    245 
    246     //return QMimeData::retrieveData(mimeType, type);
    247     return m_data;
     173        {
     174            m_enmState = Canceled;
     175        }
     176    }
     177
     178    LogFlowFunc(("Returning rc=%Rrc, m_enmState=%ld\n",
     179                 rc, m_enmState));
     180    return QMimeData::retrieveData(strMIMEType, type);
    248181}
    249182
     
    327260            for (int i = 0; i < lstData.size(); i++)
    328261            {
    329                 QString strURL = lstData.at(i).toString();
    330                 LogFlowFunc(("\tURL: %s\n",
    331                              strURL.toAscii().constData()));
    332                 lstURL << QUrl(strURL.toAscii());
     262                QFileInfo fileInfo(lstData.at(i).toString());
     263#ifdef DEBUG
     264                LogFlowFunc(("\tURL: %s (fExists=%RTbool, fIsDir=%RTbool, cb=%RU64)\n",
     265                             fileInfo.absoluteFilePath().constData(), fileInfo.exists(),
     266                             fileInfo.isDir(), fileInfo.size()));
     267#endif
     268                lstURL << QUrl::fromLocalFile(fileInfo.absoluteFilePath());
    333269            }
    334270            LogFlowFunc(("Number of URLs: %d\n",  lstURL.size()));
    335271
    336             QMimeData::setUrls(f);
     272            if (RT_SUCCESS(rc))
     273                QMimeData::setUrls(lstURL);
    337274            break;
    338275        }
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h

    r50305 r50460  
    3232#include "UIDnDHandler.h"
    3333
     34/* Forward declarations: */
     35class UIDnDDrag;
     36
    3437/** @todo Subclass QWindowsMime / QMacPasteboardMime
    3538 *  to register own/more MIME types. */
     
    4548    enum State
    4649    {
     50        /** Host is in dragging state, without
     51         *  having retrieved the metadata from the guest yet. */
    4752        Dragging = 0,
    48         DataRetrieved,
     53        /** Guest sent over the (MIME) metadata so that the
     54         *  host knows which DnD targets can be used. */
     55        MetaDataRetrieved,
     56        /** There has been a "dropped" action which indicates
     57         *  that the guest can continue sending more data (if any)
     58         *  over to the host, based on the (MIME) metadata. */
    4959        Dropped,
     60        /** The operation has been canceled. */
    5061        Canceled
    5162    };
     
    5566    UIDnDMimeData(CSession &session, QStringList formats,
    5667                  Qt::DropAction defAction,
    57                   Qt::DropActions actions, QWidget *pParent);
     68                  Qt::DropActions actions, UIDnDDrag *pParent);
    5869
    5970    int setData(const QString &mimeType);
     
    89100private:
    90101
    91     /* Private members. */
    92     QWidget          *m_pParent;
     102    UIDnDDrag        *m_pParent;
    93103    CSession          m_session;
    94104    QStringList       m_lstFormats;
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r50265 r50460  
    10921092
    10931093#ifdef VBOX_WITH_DRAG_AND_DROP
    1094 
    10951094void UIMachineView::dragEnterEvent(QDragEnterEvent *pEvent)
    10961095{
     
    11781177    gDnD->dragGHPending(session(), screenId(), this);
    11791178}
    1180 
    11811179#endif /* VBOX_WITH_DRAG_AND_DROP */
    11821180
  • trunk/src/VBox/GuestHost/Makefile.kmk

    r41477 r50460  
    55
    66#
    7 # Copyright (C) 2008-2012 Oracle Corporation
     7# Copyright (C) 2008-2014 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    3232endif
    3333
     34ifdef VBOX_WITH_DRAG_AND_DROP
     35 include $(PATH_SUB_CURRENT)/DragAndDrop/Makefile.kmk
     36endif
     37
    3438include $(FILE_KBUILD_SUB_FOOTER)
    3539
  • trunk/src/VBox/HostServices/DragAndDrop/Makefile.kmk

    r42261 r50460  
    4343        $(LIB_VMM) \
    4444        $(LIB_RUNTIME) \
    45         $(LIB_REM)
     45        $(LIB_REM) \
     46        $(PATH_STAGE_LIB)/VBoxDnDHostR3Lib$(VBOX_SUFF_LIB)
    4647
    4748VBoxDragAndDropSvc_LDFLAGS.darwin = \
  • trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp

    r50316 r50460  
    55
    66/*
    7  * Copyright (C) 2011-2013 Oracle Corporation
     7 * Copyright (C) 2011-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4848{
    4949public:
    50     DnDHGSendDirPrivate(const RTCString &strPath, uint32_t fMode, uint64_t cbSize, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser)
    51       : m_strPath(strPath)
    52       , m_cbSize(cbSize)
    53       , m_pfnProgressCallback(pfnProgressCallback)
    54       , m_pvProgressUser(pvProgressUser)
     50
     51    DnDHGSendDirPrivate(const RTCString &strPath,
     52                        uint32_t fMode, uint64_t cbSize,
     53                        PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser)
     54        : m_strPath(strPath)
     55        , m_cbSize(cbSize)
     56        , m_pfnProgressCallback(pfnProgressCallback)
     57        , m_pvProgressUser(pvProgressUser)
    5558    {
    5659        VBOXHGCMSVCPARM paTmpParms[3];
    5760        paTmpParms[0].setString(m_strPath.c_str());
    58         paTmpParms[1].setUInt32(m_strPath.length() + 1);
     61        paTmpParms[1].setUInt32((uint32_t)(m_strPath.length() + 1));
    5962        paTmpParms[2].setUInt32(fMode);
    6063
     
    7477
    7578protected:
    76     RTCString m_strPath;
     79    RTCString              m_strPath;
    7780
    7881    /* Progress stuff */
     
    9093{
    9194public:
    92     DnDHGSendFilePrivate(const RTCString &strHostPath, const RTCString &strGuestPath, uint32_t fMode, uint64_t cbSize, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser);
    93     virtual ~DnDHGSendFilePrivate();
     95
     96    DnDHGSendFilePrivate(const RTCString &strHostPath,
     97                         const RTCString &strGuestPath,
     98                         uint32_t fMode, uint64_t cbSize,
     99                         PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser);
     100    virtual ~DnDHGSendFilePrivate(void);
    94101
    95102    int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     
    117124{
    118125public:
    119     DnDHGSendDataMessagePrivate(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser);
     126
     127    DnDHGSendDataMessagePrivate(uint32_t uMsg, uint32_t cParms,
     128                                VBOXHGCMSVCPARM paParms[],
     129                                PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser);
    120130    int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    121131
     
    149159{
    150160    m_paSkelParms[0].setString(m_strGuestPath.c_str());
    151     m_paSkelParms[1].setUInt32(m_strGuestPath.length() + 1);
     161    m_paSkelParms[1].setUInt32((uint32_t)(m_strGuestPath.length() + 1));
    152162    m_paSkelParms[2].setPointer(NULL, 0);
    153163    m_paSkelParms[3].setUInt32(0);
     
    198208
    199209            /* Tell the guest the actual size. */
    200             paParms[3].setUInt32(cbRead);
     210            paParms[3].setUInt32((uint32_t)cbRead);
    201211        }
    202212    }
     
    205215    {
    206216        /* Check if we are done. */
     217        Assert(m_cbFileProcessed <= m_cbFileSize);
    207218        bool fDone = m_cbFileSize == m_cbFileProcessed;
    208219        if (!fDone)
     
    231242        {
    232243            RTFileClose(m_hCurFile);
    233             m_hCurFile = 0;
     244            m_hCurFile = NIL_RTFILE;
    234245        }
    235246    }
     
    325336                                           PFNDNDPROGRESS pfnProgressCallback,
    326337                                           void *pvProgressUser)
    327     : m_cbAll(0)
     338    : m_cbTotal(0)
    328339    , m_cbTransfered(0)
    329340    , m_pfnProgressCallback(pfnProgressCallback)
    330341    , m_pvProgressUser(pvProgressUser)
    331342{
     343    if (cParms < 5) /* Paranoia. */
     344        return;
     345
     346    const char *pszFormat = static_cast<const char*>(paParms[1].u.pointer.addr);
     347    uint32_t cbFormat = paParms[1].u.pointer.size;
     348
     349    int rc = VINF_SUCCESS;
    332350    RTCString strNewURIs;
    333351
    334     /* Check the format for any uri type. */
    335     if (hasFileUrls(static_cast<const char*>(paParms[1].u.pointer.addr),
    336                     paParms[1].u.pointer.size))
    337     {
    338         LogFlowFunc(("Old data: '%s'\n", (char*)paParms[3].u.pointer.addr));
     352    /* Do we need to build up a file tree? */
     353    if (DnDMIMEHasFileURLs(pszFormat, cbFormat))
     354    {
     355        const char *pszList = static_cast<const char*>(paParms[3].u.pointer.addr);
     356        AssertPtr(pszList);
     357        uint32_t cbList = paParms[3].u.pointer.size;
     358        Assert(cbList);
     359
     360        LogFlowFunc(("Old data: '%s'\n", pszList));
    339361
    340362        /* The list is separated by newline (even if only one file is listed). */
    341         RTCList<RTCString> lstURIOrg = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr),
    342                                                  paParms[3].u.pointer.size).split("\r\n");
     363        RTCList<RTCString> lstURIOrg
     364            = RTCString(pszList, cbList).split("\r\n");
    343365        if (!lstURIOrg.isEmpty())
    344366        {
    345             RTCList<RTCString> lstURINew;
    346             for (size_t i = 0; i < lstURIOrg.size(); ++i)
    347             {
    348                 const RTCString &strURI = lstURIOrg.at(i);
    349 
    350                 /* Query the path component of a file URI. If this hasn't a
    351                  * file scheme NULL is returned. */
    352                 char *pszFilePath;
    353                 if ((pszFilePath = RTUriFilePath(strURI.c_str(), URI_FILE_FORMAT_AUTO)))
    354                 {
    355                     /* Add the path to our internal file list (recursive in
    356                      * the case of a directory). */
    357                     char *pszFilename;
    358                     if ((pszFilename = RTPathFilename(pszFilePath)))
    359                     {
    360                         char *pszNewURI = RTUriFileCreate(pszFilename);
    361                         if (pszNewURI)
    362                         {
    363                             lstURINew.append(pszNewURI);
    364                             RTStrFree(pszNewURI);
    365 
    366                             buildFileTree(pszFilePath, pszFilename - pszFilePath);
    367                         }
    368                     }
    369 
    370                     RTStrFree(pszFilePath);
    371                 }
    372                 else /* Just append the raw data. */
    373                     lstURINew.append(strURI);
    374             }
    375 
    376             /* We have to change the actual DnD data. Remove any host paths and
    377              * just decode the filename into the new data. The guest tools will
    378              * add the correct path again, before sending the DnD drop event to
    379              * some window. */
    380             strNewURIs = RTCString::join(lstURINew, "\r\n") + "\r\n";
    381 
    382             /* Note: We don't delete the old pointer here, cause this is done
    383              *       by the caller. We just use the RTString data, which has the
    384              *       scope of this ctor. This is enough cause the data is copied in
    385              *       the DnDHGSendDataMessagePrivate anyway. */
    386             paParms[3].u.pointer.addr = (void*)strNewURIs.c_str();
    387             paParms[3].u.pointer.size = strNewURIs.length() + 1;
    388             paParms[4].u.uint32       = strNewURIs.length() + 1;
     367            rc = m_lstURI.AppendPathsFromList(lstURIOrg, 0 /* fFlags */);
     368            if (RT_SUCCESS(rc))
     369            {
     370                /* Add the total size of all meta data + files transferred to
     371                 * the message's total count. */
     372                m_cbTotal += m_lstURI.TotalBytes();
     373
     374                /* We have to change the actual DnD data. Remove any host paths and
     375                 * just decode the filename into the new data. The guest tools will
     376                 * add the correct path again, before sending the DnD drop event to
     377                 * some window. */
     378                strNewURIs = m_lstURI.RootToString();
     379
     380                /* Note: We don't delete the old pointer here, cause this is done
     381                 *       by the caller. We just use the RTString data, which has the
     382                 *       scope of this ctor. This is enough cause the data is copied in
     383                 *       the DnDHGSendDataMessagePrivate anyway. */
     384                paParms[3].u.pointer.addr = (void *)strNewURIs.c_str();
     385                paParms[3].u.pointer.size = (uint32_t)(strNewURIs.length() + 1);
     386                paParms[4].u.uint32       = (uint32_t)(strNewURIs.length() + 1);
     387
     388                LogFlowFunc(("Set new data: '%s'\n", (char*)paParms[3].u.pointer.addr));
     389            }
    389390        }
    390391    }
    391392
    392393    /* Add the size of the data to the todo list. */
    393     m_cbAll += paParms[4].u.uint32;
     394    m_cbTotal += paParms[4].u.uint32;
     395    LogFlowFunc(("cbTotal=%zu\n", m_cbTotal));
    394396
    395397    /* The first message is the meta info for the data and the data itself. */
    396398    m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms,
    397399                                                     &DnDHGSendDataMessage::progressCallback, this);
    398 #ifdef DEBUG
    399     LogFlowFunc(("new data '%s'\n", (char*)paParms[3].u.pointer.addr));
    400     LogFlowFunc(("cbAll: %zu\n", m_cbAll));
    401     LogFlowFunc(("cbData: %RU32\n", paParms[4].u.uint32));
    402 
    403     for (size_t i = 0; i < m_uriList.size(); ++i)
    404         LogFlowFunc(("file: %s : %s - %o - %ld\n",
    405                      m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(),
    406                      m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize));
    407 #endif
    408400}
    409401
     
    430422}
    431423
    432 int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     424int DnDHGSendDataMessage::currentMessage(uint32_t uMsg,
     425                                         uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    433426{
    434427    if (!m_pNextPathMsg)
     
    444437    }
    445438
    446     /* File data to send? */
     439    /* File/directory data to send? */
    447440    if (!m_pNextPathMsg)
    448441    {
    449         if (m_uriList.isEmpty())
     442        if (m_lstURI.IsEmpty())
    450443            return rc;
     444
    451445        /* Create new messages based on our internal path list. Currently
    452446         * this could be directories or regular files. */
    453         PathEntry nextPath = m_uriList.first();
     447        const DnDURIPath &nextPath = m_lstURI.First();
    454448        try
    455449        {
     450            LogFlowFunc(("Processing srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n",
     451                         nextPath.m_strSrcPath.c_str(), nextPath.m_strDstPath.c_str(),
     452                         nextPath.m_fMode, nextPath.m_cbSize,
     453                         RTFS_IS_DIRECTORY(nextPath.m_fMode), RTFS_IS_FILE(nextPath.m_fMode)));
     454
    456455            if (RTFS_IS_DIRECTORY(nextPath.m_fMode))
    457                 m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strGuestPath,
     456                m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strDstPath,
    458457                                                         nextPath.m_fMode, nextPath.m_cbSize,
    459                                                          &DnDHGSendDataMessage::progressCallback, this);
     458                                                         &DnDHGSendDataMessage::progressCallback,
     459                                                         this /* pvProgressUser */);
    460460            else if (RTFS_IS_FILE(nextPath.m_fMode))
    461                 m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strHostPath, nextPath.m_strGuestPath,
     461                m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strSrcPath, nextPath.m_strDstPath,
    462462                                                          nextPath.m_fMode, nextPath.m_cbSize,
    463                                                           &DnDHGSendDataMessage::progressCallback, this);
     463                                                          &DnDHGSendDataMessage::progressCallback,
     464                                                          this /* pvProgressUser */);
    464465            else
    465                 AssertMsgFailedReturn(("type '%d' is not supported for path '%s'",
    466                                        nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA);
    467 
    468             m_uriList.removeFirst();
     466                AssertMsgFailedReturn(("fMode=0x%x is not supported for srcPath=%s, dstPath=%s\n",
     467                                       nextPath.m_fMode, nextPath.m_strSrcPath.c_str(), nextPath.m_strDstPath),
     468                                       VERR_NO_DATA);
     469
     470            m_lstURI.RemoveFirst();
    469471        }
    470472        catch(std::bad_alloc &)
     
    473475        }
    474476    }
    475 
    476     return rc;
    477 }
    478 
    479 bool DnDHGSendDataMessage::hasFileUrls(const char *pcszFormat, size_t cbMax) const
    480 {
    481     LogFlowFunc(("format %s\n", pcszFormat));
    482 
    483     /** @todo text/uri also an official variant? */
    484     return (   RTStrNICmp(pcszFormat, "text/uri-list", cbMax)             == 0
    485             || RTStrNICmp(pcszFormat, "x-special/gnome-icon-list", cbMax) == 0);
    486 }
    487 
    488 int DnDHGSendDataMessage::buildFileTree(const char *pcszPath, size_t cbBaseLen)
    489 {
    490     RTFSOBJINFO objInfo;
    491     int rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING);
    492     if (RT_FAILURE(rc))
    493         return rc;
    494 
    495     /*
    496      * These are the types we currently support. Symlinks are not directly
    497      * supported. First the guest could be an OS which doesn't support it and
    498      * second the symlink could point to a file which is out of the base tree.
    499      * Both things are hard to support. For now we just copy the target file in
    500      * this case.
    501      */
    502     if (!(   RTFS_IS_DIRECTORY(objInfo.Attr.fMode)
    503           || RTFS_IS_FILE(objInfo.Attr.fMode)
    504           || RTFS_IS_SYMLINK(objInfo.Attr.fMode)))
    505         return VINF_SUCCESS;
    506 
    507     uint64_t cbSize = 0;
    508     rc = RTFileQuerySize(pcszPath, &cbSize);
    509     if (rc == VERR_IS_A_DIRECTORY)
    510         rc = VINF_SUCCESS;
    511 
    512     if (RT_FAILURE(rc))
    513         return rc;
    514 
    515     m_uriList.append(PathEntry(pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize));
    516     m_cbAll += cbSize;
    517     LogFlowFunc(("cbFile: %RU64\n", cbSize));
    518 
    519     PRTDIR hDir;
    520     /* We have to try to open even symlinks, cause they could be symlinks
    521      * to directories. */
    522     rc = RTDirOpen(&hDir, pcszPath);
    523     /* The following error happens when this was a symlink to an file or a
    524      * regular file. */
    525     if (rc == VERR_PATH_NOT_FOUND)
    526         return VINF_SUCCESS;
    527     if (RT_FAILURE(rc))
    528         return rc;
    529 
    530     while (RT_SUCCESS(rc))
    531     {
    532         RTDIRENTRY DirEntry;
    533         rc = RTDirRead(hDir, &DirEntry, NULL);
    534         if (RT_FAILURE(rc))
    535         {
    536             if (rc == VERR_NO_MORE_FILES)
    537                 rc = VINF_SUCCESS;
    538             break;
    539         }
    540         switch (DirEntry.enmType)
    541         {
    542             case RTDIRENTRYTYPE_DIRECTORY:
    543             {
    544                 /* Skip "." and ".." entries. */
    545                 if (   RTStrCmp(DirEntry.szName, ".")  == 0
    546                     || RTStrCmp(DirEntry.szName, "..") == 0)
    547                     break;
    548                 if (char *pszRecDir = RTStrAPrintf2("%s%c%s", pcszPath, RTPATH_DELIMITER, DirEntry.szName))
    549                 {
    550                     rc = buildFileTree(pszRecDir, cbBaseLen);
    551                     RTStrFree(pszRecDir);
    552                 }
    553                 else
    554                     rc = VERR_NO_MEMORY;
    555                 break;
    556             }
    557             case RTDIRENTRYTYPE_SYMLINK:
    558             case RTDIRENTRYTYPE_FILE:
    559             {
    560                 char *pszNewFile;
    561                 if ((pszNewFile = RTStrAPrintf2("%s%c%s", pcszPath, RTPATH_DELIMITER, DirEntry.szName)))
    562                 {
    563                     /* We need the size and the mode of the file. */
    564                     RTFSOBJINFO objInfo1;
    565                     rc = RTPathQueryInfo(pszNewFile, &objInfo1, RTFSOBJATTRADD_NOTHING);
    566                     if (RT_FAILURE(rc))
    567                         return rc;
    568                     rc = RTFileQuerySize(pszNewFile, &cbSize);
    569                     if (RT_FAILURE(rc))
    570                         break;
    571 
    572                     m_uriList.append(PathEntry(pszNewFile, &pszNewFile[cbBaseLen],
    573                                                objInfo1.Attr.fMode, cbSize));
    574                     m_cbAll += cbSize;
    575 
    576                     RTStrFree(pszNewFile);
    577                 }
    578                 else
    579                     rc = VERR_NO_MEMORY;
    580                 break;
    581             }
    582 
    583             default:
    584                 break;
    585         }
    586     }
    587 
    588     RTDirClose(hDir);
    589477
    590478    return rc;
     
    601489    pSelf->m_cbTransfered += cbDone;
    602490
    603     /* Advance progress info */
     491    /* Advance progress info. */
    604492    int rc = VINF_SUCCESS;
    605493    if (   pSelf->m_pfnProgressCallback
    606         && pSelf->m_cbAll)
    607     {
    608         rc = pSelf->m_pfnProgressCallback((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbAll,
     494        && pSelf->m_cbTotal)
     495    {
     496        AssertMsg(pSelf->m_cbTransfered <= pSelf->m_cbTotal,
     497                  ("More bytes transferred (%zu) than expected (%zu), cbDone=%zu\n",
     498                   pSelf->m_cbTransfered, pSelf->m_cbTotal, cbDone));
     499
     500        unsigned uPercentage = (unsigned)((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbTotal);
     501        rc = pSelf->m_pfnProgressCallback(RT_CLAMP(uPercentage, 0, 100),
    609502                                          DragAndDropSvc::DND_PROGRESS_RUNNING,
    610503                                          VINF_SUCCESS /* rc */, pSelf->m_pvProgressUser);
  • trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h

    r50308 r50460  
    44
    55/*
    6  * Copyright (C) 2011-2012 Oracle Corporation
     6 * Copyright (C) 2011-2014 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1818#define ___VBox_HostService_DnD_dndmanager_h
    1919
     20#include <VBox/GuestHost/DragAndDrop.h>
    2021#include <VBox/HostServices/Service.h>
    2122#include <VBox/HostServices/DragAndDropSvc.h>
     
    3435{
    3536public:
    36     DnDMessage()
    37       : m_pNextMsg(NULL)
    38     {
    39     }
    40     virtual ~DnDMessage()
     37
     38    DnDMessage(void)
     39        : m_pNextMsg(NULL)
     40    {
     41    }
     42
     43    virtual ~DnDMessage(void)
    4144    {
    4245        clearNextMsg();
    4346    }
    4447
    45     virtual HGCM::Message* nextHGCMMessage()
     48    virtual HGCM::Message* nextHGCMMessage(void)
    4649    {
    4750        return m_pNextMsg;
    4851    }
     52
    4953    virtual int currentMessageInfo(uint32_t *puMsg, uint32_t *pcParms)
    5054    {
     
    6064        return VINF_SUCCESS;
    6165    }
    62     virtual int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     66
     67    virtual int currentMessage(uint32_t uMsg, uint32_t cParms,
     68                               VBOXHGCMSVCPARM paParms[])
    6369    {
    6470        if (!m_pNextMsg)
     
    7177        return rc;
    7278    }
    73     virtual void clearNextMsg()
     79
     80    virtual void clearNextMsg(void)
    7481    {
    7582        if (m_pNextMsg)
     
    8087    }
    8188
    82     virtual bool isMessageWaiting() const { return m_pNextMsg != NULL; }
     89    virtual bool isMessageWaiting(void) const { return m_pNextMsg != NULL; }
    8390
    8491protected:
     92
    8593    HGCM::Message *m_pNextMsg;
    8694};
     
    106114public:
    107115
    108     DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser);
     116    DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms,
     117                         VBOXHGCMSVCPARM paParms[],
     118                         PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser);
     119
    109120    virtual ~DnDHGSendDataMessage(void);
    110121
     
    117128protected:
    118129
    119     struct PathEntry
    120     {
    121         PathEntry(const RTCString &strHostPath, const RTCString &strGuestPath, uint32_t fMode, uint64_t cbSize)
    122             : m_strHostPath(strHostPath)
    123             , m_strGuestPath(strGuestPath)
    124             , m_fMode(fMode)
    125             , m_cbSize(cbSize) {}
    126         RTCString m_strHostPath;
    127         RTCString m_strGuestPath;
    128         uint32_t  m_fMode;
    129         uint64_t  m_cbSize;
    130     };
    131 
    132     bool hasFileUrls(const char *pcszFormat, size_t cbMax) const;
    133     int buildFileTree(const char *pcszPath, size_t cbBaseLen);
    134130    static DECLCALLBACK(int) progressCallback(size_t cbDone, void *pvUser);
    135131
    136     RTCList<PathEntry>  m_uriList;
    137132    DnDMessage         *m_pNextPathMsg;
    138133
    139     /* Total size (in bytes). */
    140     size_t              m_cbAll;
    141     /* Transferred size (in bytes). */
     134    DnDURIList          m_lstURI;
     135    /* Total message size (in bytes). */
     136    size_t              m_cbTotal;
     137    /* Transferred message size (in bytes). */
    142138    size_t              m_cbTransfered;
     139
    143140    PFNDNDPROGRESS      m_pfnProgressCallback;
    144141    void               *m_pvProgressUser;
     
    152149{
    153150public:
    154     DnDHGCancelMessage()
    155     {
    156         m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL, 0, 0);
     151
     152    DnDHGCancelMessage(void)
     153    {
     154        m_pNextMsg
     155            = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL,
     156                                0 /* cParms */, 0 /* aParms */);
    157157    }
    158158};
     
    165165{
    166166public:
     167
    167168    DnDManager(PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser)
    168       : m_pCurMsg(0)
    169       , m_fOpInProcess(false)
    170       , m_pfnProgressCallback(pfnProgressCallback)
    171       , m_pvProgressUser(pvProgressUser)
     169        : m_pCurMsg(0)
     170        , m_fOpInProcess(false)
     171        , m_pfnProgressCallback(pfnProgressCallback)
     172        , m_pvProgressUser(pvProgressUser)
    172173    {}
    173     virtual ~DnDManager()
     174
     175    virtual ~DnDManager(void)
    174176    {
    175177        clear();
     
    178180    int addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    179181
    180     HGCM::Message *nextHGCMMessage();
     182    HGCM::Message *nextHGCMMessage(void);
    181183    int nextMessageInfo(uint32_t *puMsg, uint32_t *pcParms);
    182184    int nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    183185
    184     void clear();
    185 
    186     bool hasActiveOperation() const { return m_fOpInProcess; }
     186    void clear(void);
     187
     188    bool hasActiveOperation(void) const { return m_fOpInProcess; }
    187189
    188190private:
     
    196198    void                 *m_pvProgressUser;
    197199};
    198 
    199200#endif /* ___VBox_HostService_DnD_dndmanager_h */
    200201
  • trunk/src/VBox/HostServices/DragAndDrop/service.cpp

    r50308 r50460  
    470470        DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA data;
    471471        data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS;
    472         data.uPercentage  = uPercentage;
     472        data.uPercentage  = RT_CLAMP(uPercentage, 0, 100);
    473473        data.uState       = uState;
    474474        data.rc           = rc;
  • trunk/src/VBox/Main/Makefile.kmk

    r50313 r50460  
    392392        $(if $(VBOX_WITH_XPCOM),src-server/xpcom/server.cpp,)
    393393
    394 ifn1of ($(KBUILD_TARGET), win darwin) 
     394ifn1of ($(KBUILD_TARGET), win darwin)
    395395        VBoxSVC_SOURCES += $(PATH_ROOT)/src/VBox/Devices/Network/slirp/resolv_conf_parser.c
    396396endif
     
    663663 VBoxC_LIBS += $(PATH_STAGE_LIB)/VBoxOGLTest$(VBOX_SUFF_LIB)
    664664 VBoxC_LDFLAGS.darwin += -framework OpenGL
     665endif
     666
     667ifdef VBOX_WITH_DRAG_AND_DROP
     668 VBoxC_LIBS += $(PATH_STAGE_LIB)/VBoxDnDHostR3Lib$(VBOX_SUFF_LIB)
    665669endif
    666670
  • trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp

    r50265 r50460  
    2424# include "GuestDnDImpl.h"
    2525
     26# include <iprt/dir.h>
     27# include <iprt/path.h>
     28# include <iprt/stream.h>
     29# include <iprt/semaphore.h>
     30# include <iprt/cpp/utils.h>
     31
    2632# include <VMMDev.h>
    2733
    2834# include <VBox/com/list.h>
     35# include <VBox/GuestHost/DragAndDrop.h>
    2936# include <VBox/HostServices/DragAndDropSvc.h>
    3037
     
    3441# define LOG_GROUP LOG_GROUP_GUEST_DND
    3542# include <VBox/log.h>
    36 
    37 # include <iprt/stream.h>
    38 # include <iprt/semaphore.h>
    39 # include <iprt/cpp/utils.h>
    4043
    4144/* How does this work:
     
    209212};
    210213
     214/** @todo This class needs a major cleanup. Later. */
    211215class GuestDnDPrivate
    212216{
    213217private:
    214     /* todo: currently we only support one response. Maybe this needs to be extended at some time. */
     218
     219    /** @todo Currently we only support one response. Maybe this needs to be extended at some time. */
    215220    GuestDnDPrivate(GuestDnD *q, const ComObjPtr<Guest>& pGuest)
    216221        : q_ptr(q)
     
    225230    void hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;
    226231
    227     /* Static helper */
     232    /* Static helpers. */
    228233    static RTCString           toFormatString(ComSafeArrayIn(IN_BSTR, formats));
    229234    static void                toFormatSafeArray(const RTCString &strFormats, ComSafeArrayOut(BSTR, formats));
     
    238243    ComObjPtr<Guest>                 p;
    239244
    240     /* Private helper members */
     245    /* Private helper members. */
    241246    static const RTCList<RTCString>  m_sstrAllowedMimeTypes;
    242247    DnDGuestResponse                *m_pDnDResponse;
     
    396401    ComPtr<IDisplay> pDisplay;
    397402    HRESULT rc = p->mParent->COMGETTER(Display)(pDisplay.asOutParam());
    398     if (FAILED(rc)) throw rc;
     403    if (FAILED(rc))
     404        throw rc;
     405
    399406    ComPtr<IFramebuffer> pFramebuffer;
    400407    LONG xShift, yShift;
    401     rc = pDisplay->GetFramebuffer(uScreenId, pFramebuffer.asOutParam(), &xShift, &yShift);
    402     if (FAILED(rc)) throw rc;
     408    rc = pDisplay->GetFramebuffer(uScreenId, pFramebuffer.asOutParam(),
     409                                  &xShift, &yShift);
     410    if (FAILED(rc))
     411        throw rc;
     412
    403413    *puX += xShift;
    404414    *puY += yShift;
     
    696706}
    697707
    698 HRESULT GuestDnD::dragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction)
     708HRESULT GuestDnD::dragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY,
     709                             DragAndDropAction_T defaultAction,
     710                             ComSafeArrayIn(DragAndDropAction_T, allowedActions),
     711                             ComSafeArrayIn(IN_BSTR, formats),
     712                             BSTR *pstrFormat,
     713                             DragAndDropAction_T *pResultAction)
    699714{
    700715    DPTR(GuestDnD);
     
    783798        pDnD->resetProgress(p);
    784799
     800        /* Note: The actual data transfer of files/directoies is performed by the
     801         *       DnD host service. */
    785802        d->hostCall(DragAndDropSvc::HOST_DND_HG_SND_DATA,
    786803                    i,
     
    854871
    855872    Utf8Str strFormat(bstrFormat);
    856     HRESULT rc = S_OK;
     873    HRESULT hr = S_OK;
    857874
    858875    uint32_t uAction = d->toHGCMAction(action);
     
    861878        return S_OK;
    862879
     880    const char *pcszFormat = strFormat.c_str();
     881    LogFlowFunc(("strFormat=%s, uAction=0x%x\n", pcszFormat, uAction));
     882    if (DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat)))
     883    {
     884        char szDropDir[RTPATH_MAX];
     885        int rc = DnDDirCreateDroppedFiles(szDropDir, sizeof(szDropDir));
     886        if (RT_FAILURE(rc))
     887            return p->setError(VBOX_E_IPRT_ERROR,
     888                               p->tr("Unable to create the temporary drag'n drop directory \"%s\" (%Rrc)\n"),
     889                               szDropDir, rc);
     890        LogFlowFunc(("Dropped files directory on the host is: %s\n", szDropDir));
     891    }
     892
    863893    try
    864894    {
    865         LogFlowFunc(("strFormat=%s, uAction=0x%x\n", strFormat.c_str(), uAction));
    866 
    867895        VBOXHGCMSVCPARM paParms[3];
    868896        int i = 0;
     
    872900
    873901        DnDGuestResponse *pDnD = d->response();
     902
    874903        /* Reset any old data and the progress status. */
    875904        pDnD->reset();
     
    885914    catch (HRESULT rc2)
    886915    {
    887         rc = rc2;
    888     }
    889 
    890     return rc;
     916        hr = rc2;
     917    }
     918
     919    return hr;
    891920}
    892921
     
    906935        if (cbData)
    907936        {
    908             /* Copy the data into an safe array of bytes. */
     937            /* Copy the data into a safe array of bytes. */
    909938            const void *pvData = pDnD->data();
    910939            if (sfaData.resize(cbData))
     
    10061035            if (RT_SUCCESS(rc))
    10071036            {
     1037                /** @todo Store pCBData->cbAllSize in the guest's response struct
     1038                 *        if not set already. */
    10081039                uint32_t cbTotalSize = pCBData->cbAllSize;
    10091040                unsigned int cPercentage;
     
    10151046                /** @todo Don't use anonymous enums. */
    10161047                uint32_t uState = DragAndDropSvc::DND_PROGRESS_RUNNING;
    1017                 if (   pCBData->cbAllSize == cbCurSize
     1048                if (   cbTotalSize == cbCurSize
    10181049                    /* Empty data? Should not happen, but anyway ... */
    1019                     || !pCBData->cbAllSize)
     1050                    || !cbTotalSize)
    10201051                {
    10211052                    uState = DragAndDropSvc::DND_PROGRESS_COMPLETE;
     
    10241055                rc = pResp->setProgress(cPercentage, uState);
    10251056            }
    1026             /* Todo: for now we instantly confirm the cancel. Check if the
    1027              * guest should first clean up stuff itself and than really confirm
    1028              * the cancel request by an extra message. */
     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. */
    10291061            if (rc == VERR_CANCELLED)
    10301062                pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED);
     
    10531085    return rc;
    10541086}
    1055 
    10561087#endif /* VBOX_WITH_DRAG_AND_DROP */
    10571088
  • trunk/src/VBox/Main/src-client/GuestImpl.cpp

    r50370 r50460  
    838838}
    839839
    840 STDMETHODIMP Guest::DragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
     840STDMETHODIMP Guest::DragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY,
     841                                DragAndDropAction_T defaultAction,
     842                                ComSafeArrayIn(DragAndDropAction_T, allowedActions),
     843                                ComSafeArrayIn(IN_BSTR, formats),
     844                                DragAndDropAction_T *pResultAction)
    841845{
    842846    /* Input validation */
     
    849853
    850854#ifdef VBOX_WITH_DRAG_AND_DROP
    851     return m_pGuestDnD->dragHGEnter(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pResultAction);
     855    return m_pGuestDnD->dragHGEnter(uScreenId, uX, uY, defaultAction,
     856                                    ComSafeArrayInArg(allowedActions),
     857                                    ComSafeArrayInArg(formats),
     858                                    pResultAction);
    852859#else /* VBOX_WITH_DRAG_AND_DROP */
    853860    ReturnComNotImplemented();
     
    855862}
    856863
    857 STDMETHODIMP Guest::DragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction)
     864STDMETHODIMP Guest::DragHGMove(ULONG uScreenId, ULONG uX, ULONG uY,
     865                               DragAndDropAction_T defaultAction,
     866                               ComSafeArrayIn(DragAndDropAction_T, allowedActions),
     867                               ComSafeArrayIn(IN_BSTR, formats),
     868                               DragAndDropAction_T *pResultAction)
    858869{
    859870    /* Input validation */
     
    866877
    867878#ifdef VBOX_WITH_DRAG_AND_DROP
    868     return m_pGuestDnD->dragHGMove(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pResultAction);
     879    return m_pGuestDnD->dragHGMove(uScreenId, uX, uY, defaultAction,
     880                                   ComSafeArrayInArg(allowedActions),
     881                                   ComSafeArrayInArg(formats),
     882                                   pResultAction);
    869883#else /* VBOX_WITH_DRAG_AND_DROP */
    870884    ReturnComNotImplemented();
     
    884898}
    885899
    886 STDMETHODIMP Guest::DragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction)
     900STDMETHODIMP Guest::DragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY,
     901                               DragAndDropAction_T defaultAction,
     902                               ComSafeArrayIn(DragAndDropAction_T, allowedActions),
     903                               ComSafeArrayIn(IN_BSTR, formats),
     904                               BSTR *pstrFormat, DragAndDropAction_T *pResultAction)
    887905{
    888906    /* Input validation */
     
    896914
    897915#ifdef VBOX_WITH_DRAG_AND_DROP
    898     return m_pGuestDnD->dragHGDrop(uScreenId, uX, uY, defaultAction, ComSafeArrayInArg(allowedActions), ComSafeArrayInArg(formats), pstrFormat, pResultAction);
     916    return m_pGuestDnD->dragHGDrop(uScreenId, uX, uY,
     917                                   defaultAction,
     918                                   ComSafeArrayInArg(allowedActions),
     919                                   ComSafeArrayInArg(formats),
     920                                   pstrFormat, pResultAction);
    899921#else /* VBOX_WITH_DRAG_AND_DROP */
    900922    ReturnComNotImplemented();
     
    902924}
    903925
    904 STDMETHODIMP Guest::DragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress)
     926STDMETHODIMP Guest::DragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat,
     927                                  ComSafeArrayIn(BYTE, data),
     928                                  IProgress **ppProgress)
    905929{
    906930    /* Input validation */
     
    913937
    914938#ifdef VBOX_WITH_DRAG_AND_DROP
    915     return m_pGuestDnD->dragHGPutData(uScreenId, bstrFormat, ComSafeArrayInArg(data), ppProgress);
     939    return m_pGuestDnD->dragHGPutData(uScreenId, bstrFormat,
     940                                      ComSafeArrayInArg(data), ppProgress);
    916941#else /* VBOX_WITH_DRAG_AND_DROP */
    917942    ReturnComNotImplemented();
     
    919944}
    920945
    921 STDMETHODIMP Guest::DragGHPending(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction)
     946STDMETHODIMP Guest::DragGHPending(ULONG uScreenId,
     947                                  ComSafeArrayOut(BSTR, formats),
     948                                  ComSafeArrayOut(DragAndDropAction_T, allowedActions),
     949                                  DragAndDropAction_T *pDefaultAction)
    922950{
    923951    /* Input validation */
     
    930958
    931959#if defined(VBOX_WITH_DRAG_AND_DROP) && defined(VBOX_WITH_DRAG_AND_DROP_GH)
    932     return m_pGuestDnD->dragGHPending(uScreenId, ComSafeArrayOutArg(formats), ComSafeArrayOutArg(allowedActions), pDefaultAction);
     960    return m_pGuestDnD->dragGHPending(uScreenId,
     961                                      ComSafeArrayOutArg(formats),
     962                                      ComSafeArrayOutArg(allowedActions),
     963                                      pDefaultAction);
    933964#else /* VBOX_WITH_DRAG_AND_DROP */
    934965    ReturnComNotImplemented();
     
    936967}
    937968
    938 STDMETHODIMP Guest::DragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, IProgress **ppProgress)
     969STDMETHODIMP Guest::DragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action,
     970                                  IProgress **ppProgress)
    939971{
    940972    /* Input validation */
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