VirtualBox

Ignore:
Timestamp:
Jul 3, 2019 1:28:33 PM (5 years ago)
Author:
vboxsync
Message:

Shared Clipboard/URI: Update.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp

    r79366 r79497  
    3434#include <iprt/win/shlwapi.h>
    3535
     36#include <iprt/err.h>
    3637#include <iprt/path.h>
    3738#include <iprt/semaphore.h>
     
    121122        m_enmStatus = Initialized;
    122123
    123         int rc2 = RTSemEventCreate(&m_EventMetaDataComplete);
     124        int rc2 = RTSemEventCreate(&m_EventListComplete);
    124125        AssertRC(rc2);
     126        rc2 = RTSemEventCreate(&m_EventTransferComplete);
     127        AssertRC(rc2);
    125128    }
    126129
     
    130133VBoxClipboardWinDataObject::~VBoxClipboardWinDataObject(void)
    131134{
    132     RTSemEventDestroy(m_EventMetaDataComplete);
     135    RTSemEventDestroy(m_EventListComplete);
     136    RTSemEventDestroy(m_EventTransferComplete);
    133137
    134138    if (m_pStream)
     
    216220}
    217221
     222/* static */
     223
     224/**
     225 * Thread for reading URI data.
     226 * The data object needs the (high level, root) URI listing at the time of ::GetData(), so we need
     227 * to block and wait until we have this data (via this thread) and continue.
     228 *
     229 * @returns VBox status code.
     230 * @param   ThreadSelf          Thread handle. Unused at the moment.
     231 * @param   pvUser              Pointer to user-provided data. Of type VBoxClipboardWinDataObject.
     232 */
     233DECLCALLBACK(int) VBoxClipboardWinDataObject::readThread(RTTHREAD ThreadSelf, void *pvUser)
     234{
     235    RT_NOREF(ThreadSelf);
     236
     237    LogFlowFuncEnter();
     238
     239    VBoxClipboardWinDataObject *pThis = (VBoxClipboardWinDataObject *)pvUser;
     240
     241    PSHAREDCLIPBOARDURITRANSFER pTransfer = pThis->m_pTransfer;
     242    AssertPtr(pTransfer);
     243
     244    pTransfer->Thread.fStarted = true;
     245
     246    RTThreadUserSignal(RTThreadSelf());
     247
     248    int rc = SharedClipboardURITransferOpen(pTransfer);
     249    if (RT_SUCCESS(rc))
     250    {
     251        VBOXCLIPBOARDLISTHDR Hdr;
     252        rc = SharedClipboardURIListHdrInit(&Hdr);
     253        if (RT_SUCCESS(rc))
     254        {
     255            VBOXCLIPBOARDLISTHANDLE hList;
     256            rc = SharedClipboardURITransferListOpen(pTransfer, &Hdr, &hList);
     257            if (RT_SUCCESS(rc))
     258            {
     259                LogFlowFunc(("hList=%RU64, cTotalObjects=%RU64, cbTotalSize=%RU64\n\n",
     260                             hList, Hdr.cTotalObjects, Hdr.cbTotalSize));
     261
     262                for (uint64_t i = 0; i < Hdr.cTotalObjects; i++)
     263                {
     264                    VBOXCLIPBOARDLISTENTRY Entry;
     265                    rc = SharedClipboardURITransferListRead(pTransfer, hList, &Entry);
     266                    if (RT_SUCCESS(rc))
     267                    {
     268
     269                    }
     270                    else
     271                        break;
     272
     273                    if (pTransfer->Thread.fStop)
     274                        break;
     275                }
     276
     277                if (RT_SUCCESS(rc))
     278                {
     279                    /*
     280                     * Signal the "list complete" event so that this data object can return (valid) data via ::GetData().
     281                     * This in turn then will create IStream instances (by the OS) for each file system object to handle.
     282                     */
     283                    int rc2 = RTSemEventSignal(pThis->m_EventListComplete);
     284                    AssertRC(rc2);
     285
     286                    LogFlowFunc(("Waiting for transfer to complete ...\n"));
     287
     288                    /* Transferring stuff can take a while, so don't use any timeout here. */
     289                    rc2 = RTSemEventWait(pThis->m_EventTransferComplete, RT_INDEFINITE_WAIT);
     290                    AssertRC(rc2);
     291                }
     292
     293                SharedClipboardURITransferListClose(pTransfer, hList);
     294            }
     295
     296            SharedClipboardURIListHdrDestroy(&Hdr);
     297        }
     298
     299        SharedClipboardURITransferClose(pTransfer);
     300    }
     301
     302    LogFlowFuncLeaveRC(rc);
     303    return rc;
     304}
     305
    218306/**
    219307 * Creates a FILEGROUPDESCRIPTOR object from a given URI transfer and stores the result into an HGLOBAL object.
     
    232320    LogFlowFuncEnter();
    233321
    234     SharedClipboardURIList *pURIList = SharedClipboardURITransferGetList(pTransfer);
    235     if (!pURIList)
    236         return VERR_WRONG_ORDER;
    237 
    238322    const size_t cbFileGroupDescriptor = fUnicode ? sizeof(FILEGROUPDESCRIPTORW) : sizeof(FILEGROUPDESCRIPTORA);
    239323    const size_t cbFileDescriptor = fUnicode ? sizeof(FILEDESCRIPTORW) : sizeof(FILEDESCRIPTORA);
    240324
    241     const UINT   cItems = (UINT)pURIList->GetRootCount(); /** @todo UINT vs. uint64_t */
     325    const UINT   cItems = (UINT)0; /** @todo UINT vs. uint64_t */
     326    if (!cItems)
     327        return VERR_NOT_FOUND;
     328
    242329    const size_t cbFGD  = cbFileGroupDescriptor + (cbFileDescriptor * (cItems - 1));
    243330
     
    254341
    255342    char *pszFileSpec = NULL;
    256 
     343#if 0
    257344    for (UINT i = 0; i < cItems; i++)
    258345    {
     
    326413#endif
    327414    }
     415#endif
    328416
    329417    if (pszFileSpec)
     
    393481#endif
    394482        {
    395             int rc = SharedClipboardURITransferPrepare(m_pTransfer);
    396             if (RT_SUCCESS(rc))
     483            const bool fUnicode = lIndex == FormatIndex_FileDescriptorW;
     484
     485            LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A"));
     486
     487            int rc;
     488
     489            /* The caller can call GetData() several times, so make sure we don't do the same transfer multiple times. */
     490            if (SharedClipboardURITransferGetStatus(m_pTransfer) == SHAREDCLIPBOARDURITRANSFERSTATUS_NONE)
    397491            {
    398                 const bool fUnicode = lIndex == FormatIndex_FileDescriptorW;
    399 
    400                 LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A"));
    401 
    402                 /* Start the transfer asynchronously in a separate thread. */
    403                 rc = SharedClipboardURITransferRun(m_pTransfer, true /* fAsync */);
     492                rc = SharedClipboardURITransferPrepare(m_pTransfer);
    404493                if (RT_SUCCESS(rc))
    405494                {
    406                     /* Wait for the meta data to arrive. */
    407                     LogFlowFunc(("Waiting for meta data to arrive ...\n"));
    408                     rc = RTSemEventWait(m_EventMetaDataComplete, 30 * 1000 /* 30s timeout */);
     495                    /* Start the transfer asynchronously in a separate thread. */
     496                    rc = SharedClipboardURITransferRun(m_pTransfer, &VBoxClipboardWinDataObject::readThread, this);
    409497                    if (RT_SUCCESS(rc))
    410498                    {
    411                         HGLOBAL hGlobal;
    412                         rc = createFileGroupDescriptorFromTransfer(m_pTransfer, fUnicode, &hGlobal);
     499                        LogFunc(("Waiting for listing to arrive ...\n"));
     500                        rc = RTSemEventWait(m_EventListComplete, 5 * 60 * 1000 /* 5 min timeout */);
    413501                        if (RT_SUCCESS(rc))
    414502                        {
    415                             pMedium->tymed   = TYMED_HGLOBAL;
    416                             pMedium->hGlobal = hGlobal;
    417                             /* Note: hGlobal now is being owned by pMedium / the caller. */
    418 
    419                             hr = S_OK;
     503                            LogFunc(("Listing complete\n"));
     504
     505                            HGLOBAL hGlobal;
     506                            rc = createFileGroupDescriptorFromTransfer(m_pTransfer, fUnicode, &hGlobal);
     507                            if (RT_SUCCESS(rc))
     508                            {
     509                                pMedium->tymed   = TYMED_HGLOBAL;
     510                                pMedium->hGlobal = hGlobal;
     511                                /* Note: hGlobal now is being owned by pMedium / the caller. */
     512
     513                                hr = S_OK;
     514                            }
    420515                        }
    421516                    }
    422517                }
    423 
    424                 if (RT_FAILURE(rc))
    425                     LogRel(("Shared Clipboard: Data object unable to receive meta data, rc=%Rrc\n", rc));
    426518            }
     519            else
     520                rc = VERR_ALREADY_EXISTS;
     521
     522            if (RT_FAILURE(rc))
     523                LogRel(("Shared Clipboard: Data object unable to get data, rc=%Rrc\n", rc));
     524
    427525            break;
    428526        }
     
    588686    LogFlowFuncLeaveRC(VINF_SUCCESS);
    589687    return VINF_SUCCESS;
    590 }
    591 
    592 DECLCALLBACK(void) VBoxClipboardWinDataObject::OnMetaDataComplete(PSHAREDCLIPBOARDURITRANSFER pTransfer)
    593 {
    594     LogFlowFuncEnter();
    595 
    596     AssertReturnVoid(pTransfer == m_pTransfer);
    597 
    598     int rc2 = RTSemEventSignal(m_EventMetaDataComplete);
    599     AssertRC(rc2);
    600688}
    601689
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