VirtualBox

Ignore:
Timestamp:
Sep 26, 2019 4:13:25 PM (5 years ago)
Author:
vboxsync
Message:

Shared Clipboard/Transfers: Update.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp

    r80993 r81025  
    6060    /** Windows-specific context data. */
    6161    SHCLWINCTX            Win;
     62    /** Thread handle for window thread. */
     63    RTTHREAD              hThread;
     64    /** Start indicator flag. */
     65    bool                  fStarted;
     66    /** Shutdown indicator flag. */
     67    bool                  fShutdown;
    6268#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    6369    /** Associated transfer data. */
     
    6571#endif
    6672} SHCLCONTEXT, *PSHCLCONTEXT;
    67 
    68 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    69 typedef struct _SHCLREADTHREADCTX
    70 {
    71     PSHCLCONTEXT     pClipboardCtx;
    72     PSHCLTRANSFER pTransfer;
    73 } SHCLREADTHREADCTX, *PSHCLREADTHREADCTX;
    74 
    75 typedef struct _SHCLWRITETHREADCTX
    76 {
    77     PSHCLCONTEXT     pClipboardCtx;
    78     PSHCLTRANSFER pTransfer;
    79 } SHCLWRITETHREADCTX, *PSHCLWRITETHREADCTX;
    80 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    8173
    8274
     
    109101static void vboxClipboardTransferCallbackCleanup(PSHCLTRANSFERCALLBACKDATA pData)
    110102{
     103    LogFlowFuncEnter();
     104
    111105    PSHCLTRANSFERCTX pCtx = (PSHCLTRANSFERCTX)pData->pvUser;
    112106    AssertPtr(pCtx);
     
    146140    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pData->pvUser;
    147141    AssertPtr(pCtx);
    148 
    149     LogFlowFunc(("pCtx=%p\n", pCtx));
     142    Assert(pData->cbUser == sizeof(SHCLCONTEXT));
    150143
    151144    PSHCLTRANSFER pTransfer = pData->pTransfer;
    152145    AssertPtr(pTransfer);
    153146
     147    const SHCLTRANSFERDIR enmDir = SharedClipboardTransferGetDir(pTransfer);
     148
     149    LogFlowFunc(("pCtx=%p, idTransfer=%RU16, enmDir=%RU32\n", pCtx, SharedClipboardTransferGetID(pTransfer), enmDir));
     150
    154151    int rc;
    155152
    156153    /* The guest wants to write local data to the host? */
    157     if (SharedClipboardTransferGetDir(pTransfer) == SHCLTRANSFERDIR_WRITE)
     154    if (enmDir == SHCLTRANSFERDIR_WRITE)
    158155    {
    159156        Assert(SharedClipboardTransferGetSource(pTransfer) == SHCLSOURCE_LOCAL); /* Sanity. */
     
    194191    }
    195192    /* The guest wants to read data from a remote source. */
    196     else if (SharedClipboardTransferGetDir(pTransfer) == SHCLTRANSFERDIR_READ)
    197     {
    198         /* The IDataObject must be created in our window thread, so post a message to it, which
    199          * then in turn takes care of the creation. */
    200         ::PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_URI_TRANSFER_START,
    201                       0 /* wParm */, (LPARAM)pTransfer /* lParm */);
    202 
    203         rc = VINF_SUCCESS;
     193    else if (enmDir == SHCLTRANSFERDIR_READ)
     194    {
     195        Assert(SharedClipboardTransferGetSource(pTransfer) == SHCLSOURCE_REMOTE); /* Sanity. */
     196
     197        rc = SharedClipboardWinTransferCreate(&pCtx->Win, pTransfer);
    204198    }
    205199    else
    206200        AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
    207201
    208     LogFlowFuncLeaveRC(rc);
     202    LogFlowFunc(("LEAVE: idTransfer=%RU16, rc=%Rrc\n", SharedClipboardTransferGetID(pTransfer), rc));
    209203    return rc;
    210204}
     
    251245        case WM_CLIPBOARDUPDATE:
    252246        {
    253             LogFunc(("WM_CLIPBOARDUPDATE\n"));
     247            LogFunc(("WM_CLIPBOARDUPDATE: pWinCtx=%p\n", pWinCtx));
    254248
    255249            int rc = RTCritSectEnter(&pWinCtx->CritSect);
     
    269263                     * Report available formats to the host. */
    270264                    SHCLFORMATDATA Formats;
    271                     int rc = SharedClipboardWinGetFormats(&pCtx->Win, &Formats);
     265                    int rc = SharedClipboardWinGetFormats(pWinCtx, &Formats);
    272266                    if (RT_SUCCESS(rc))
    273267                    {
     
    298292        case WM_DRAWCLIPBOARD:
    299293        {
    300             LogFlowFunc(("WM_DRAWCLIPBOARD\n"));
     294            LogFlowFunc(("WM_DRAWCLIPBOARD: pWinCtx=%p\n", pWinCtx));
    301295
    302296            int rc = RTCritSectEnter(&pWinCtx->CritSect);
     
    517511            Assert(pEvent->enmType == VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS);
    518512
    519             const SHCLFORMATS fFormats =  pEvent->u.ReportedFormats.uFormats;
     513            const SHCLFORMATS fFormats = pEvent->u.ReportedFormats.uFormats;
    520514
    521515            if (fFormats != VBOX_SHCL_FMT_NONE) /* Could arrive with some older GA versions. */
    522516            {
    523                 int rc = SharedClipboardWinOpen(hwnd);
    524                 if (RT_SUCCESS(rc))
    525                 {
    526                     SharedClipboardWinClear();
    527 
    528 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    529                     if (fFormats & VBOX_SHCL_FMT_URI_LIST)
     517#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     518                if (fFormats & VBOX_SHCL_FMT_URI_LIST)
     519                {
     520                    LogFunc(("VBOX_SHCL_FMT_URI_LIST\n"));
     521
     522                    /*
     523                     * Creating and starting the actual transfer will be done in vbglR3ClipboardTransferStart() as soon
     524                     * as the host announces the start of the transfer via a VBOX_SHCL_HOST_MSG_TRANSFER_STATUS message.
     525                     * Transfers always are controlled and initiated on the host side!
     526                     *
     527                     * So don't announce the transfer to the OS here yet. Don't touch the clipboard in any here; otherwise
     528                     * this will trigger a WM_DRAWCLIPBOARD or friends, which will result in fun bugs coming up.
     529                     */
     530                }
     531                else
     532                {
     533#endif
     534                    int rc = SharedClipboardWinOpen(hwnd);
     535                    if (RT_SUCCESS(rc))
    530536                    {
    531                         LogFunc(("VBOX_SHCL_FMT_URI_LIST\n"));
    532 
    533                         /*
    534                          * Creating and starting the actual transfer will be done in vbglR3ClipboardTransferStart() as soon
    535                          * as the host announces the start of the transfer via a VBOX_SHCL_HOST_MSG_TRANSFER_STATUS message.
    536                          * Transfers always are controlled and initiated on the host side!
    537                          *
    538                          * So don't announce the transfer to the OS here yet.
    539                          */
     537                        SharedClipboardWinClear();
     538
     539                        rc = SharedClipboardWinAnnounceFormats(pWinCtx, fFormats);
    540540                    }
    541                     else
    542                     {
    543 #endif
    544                         rc = SharedClipboardWinAnnounceFormats(pWinCtx, fFormats);
    545 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    546                     }
    547 #endif
     541
    548542                    SharedClipboardWinClose();
    549                 }
     543
     544#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     545                }
     546#endif
    550547            }
    551548
     
    651648        }
    652649
    653 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    654         case SHCL_WIN_WM_URI_TRANSFER_START:
    655         {
    656             LogFunc(("SHCL_WIN_WM_URI_TRANSFER_CREATE\n"));
     650#if 0
     651        case SHCL_WIN_WM_TRANSFER_START:
     652        {
     653            LogFunc(("SHCL_WIN_WM_TRANSFER_START\n"));
    657654
    658655            PSHCLTRANSFER pTransfer = (PSHCLTRANSFER)lParam;
     
    661658            Assert(SharedClipboardTransferGetSource(pTransfer) == SHCLSOURCE_REMOTE); /* Sanity. */
    662659
    663             int rc2 = SharedClipboardWinTransferCreate(&pCtx->Win, pTransfer);
     660            int rc2 = SharedClipboardWinTransferCreate(pWinCtx, pTransfer);
    664661            AssertRC(rc2);
    665662            break;
     
    707704
    708705    /* Register the Window Class. */
    709     WNDCLASSEX wc = { 0 };
    710     wc.cbSize     = sizeof(WNDCLASSEX);
     706    WNDCLASSEX wc;
     707    RT_ZERO(wc);
     708
     709    wc.cbSize = sizeof(WNDCLASSEX);
    711710
    712711    if (!GetClassInfoEx(hInstance, s_szClipWndClassName, &wc))
     
    741740                         SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
    742741
    743             SharedClipboardWinChainAdd(pWinCtx);
    744             if (!SharedClipboardWinIsNewAPI(&pWinCtx->newAPI))
    745                 pWinCtx->oldAPI.timerRefresh = SetTimer(pWinCtx->hWnd, 0, 10 * 1000 /* 10s */, NULL);
     742            rc = SharedClipboardWinChainAdd(pWinCtx);
     743            if (RT_SUCCESS(rc))
     744            {
     745                if (!SharedClipboardWinIsNewAPI(&pWinCtx->newAPI))
     746                    pWinCtx->oldAPI.timerRefresh = SetTimer(pWinCtx->hWnd, 0, 10 * 1000 /* 10s */, NULL);
     747            }
    746748        }
    747749    }
     
    751753}
    752754
     755static int vboxClipboardWindowThread(RTTHREAD hThread, void *pvUser)
     756{
     757    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pvUser;
     758    AssertPtr(pCtx);
     759
     760    HRESULT hr;
     761
     762#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     763    hr = OleInitialize(NULL);
     764    if (FAILED(hr))
     765    {
     766        LogRel(("Shared Clipboard: Initializing OLE in window thread failed (%Rhrc) -- file transfers unavailable\n", hr));
     767        /* Not critical, the rest of the clipboard might work. */
     768    }
     769    else
     770        LogRel(("Shared Clipboard: Initialized OLE in window thread\n"));
     771#endif
     772
     773    int rc = vboxClipboardCreateWindow(pCtx);
     774    if (RT_FAILURE(rc))
     775    {
     776        LogRel(("Shared Clipboard: Unable to create window, rc=%Rrc\n", rc));
     777        return rc;
     778    }
     779
     780    pCtx->fStarted = true; /* Set started indicator. */
     781
     782    int rc2 = RTThreadUserSignal(hThread);
     783    bool fSignalled = RT_SUCCESS(rc2);
     784
     785    LogRel2(("Shared Clipboard: Window thread running\n"));
     786
     787    if (RT_SUCCESS(rc))
     788    {
     789        for (;;)
     790        {
     791            MSG uMsg;
     792            BOOL fRet;
     793            while ((fRet = GetMessage(&uMsg, 0, 0, 0)) > 0)
     794            {
     795                TranslateMessage(&uMsg);
     796                DispatchMessage(&uMsg);
     797            }
     798            Assert(fRet >= 0);
     799
     800            if (ASMAtomicReadBool(&pCtx->fShutdown))
     801                break;
     802
     803            /** @todo Immediately drop on failure? */
     804        }
     805    }
     806
     807    if (!fSignalled)
     808    {
     809        rc2 = RTThreadUserSignal(hThread);
     810        AssertRC(rc2);
     811    }
     812
     813#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     814    OleSetClipboard(NULL); /* Make sure to flush the clipboard on destruction. */
     815    OleUninitialize();
     816#endif
     817
     818    LogRel(("Shared Clipboard: Window thread ended\n"));
     819
     820    LogFlowFuncLeaveRC(rc);
     821    return rc;
     822}
     823
    753824static void vboxClipboardDestroy(PSHCLCONTEXT pCtx)
    754825{
    755826    AssertPtrReturnVoid(pCtx);
     827
     828    LogFlowFunc(("pCtx=%p\n", pCtx));
     829
     830    LogRel2(("Shared Clipboard: Destroying ...\n"));
     831
     832    pCtx->fShutdown = true;
    756833
    757834    const PSHCLWINCTX pWinCtx = &pCtx->Win;
     
    763840    }
    764841
     842    if (pCtx->hThread != NIL_RTTHREAD)
     843    {
     844        int rcThread = VERR_WRONG_ORDER;
     845        int rc = RTThreadWait(pCtx->hThread, 60 * 1000 /* Timeout in ms */, &rcThread);
     846        LogFlowFunc(("Waiting for thread resulted in %Rrc (thread exited with %Rrc)\n",
     847                     rc, rcThread));
     848        RT_NOREF(rc);
     849    }
     850
    765851    UnregisterClass(s_szClipWndClassName, pCtx->pEnv->hInstance);
    766852
    767853    SharedClipboardWinCtxDestroy(&pCtx->Win);
     854
     855    LogRel2(("Shared Clipboard: Destroyed\n"));
    768856}
    769857
     
    797885    }
    798886
    799     pCtx->pEnv = pEnv;
     887    pCtx->pEnv      = pEnv;
     888    pCtx->hThread   = NIL_RTTHREAD;
     889    pCtx->fStarted  = false;
     890    pCtx->fShutdown = false;
    800891
    801892    int rc = VINF_SUCCESS;
    802893
    803894#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    804     HRESULT hr = OleInitialize(NULL);
    805     if (FAILED(hr))
    806     {
    807         LogRel(("Shared Clipboard: Initializing OLE failed (%Rhrc) -- file transfers unavailable\n", hr));
    808         /* Not critical, the rest of the clipboard might work. */
    809     }
    810     else
    811     {
    812         LogRel(("Shared Clipboard: Initialized OLE\n"));
    813 
    814         /* Install callbacks. */
    815         RT_ZERO(pCtx->CmdCtx.Transfers.Callbacks);
    816 
    817         pCtx->CmdCtx.Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */
    818 
    819         pCtx->CmdCtx.Transfers.Callbacks.pfnTransferInitialize = vboxClipboardOnTransferInitCallback;
    820         pCtx->CmdCtx.Transfers.Callbacks.pfnTransferStart      = vboxClipboardOnTransferStartCallback;
    821         pCtx->CmdCtx.Transfers.Callbacks.pfnTransferComplete   = vboxClipboardOnTransferCompleteCallback;
    822         pCtx->CmdCtx.Transfers.Callbacks.pfnTransferError      = vboxClipboardOnTransferErrorCallback;
    823     }
     895    /* Install callbacks. */
     896    RT_ZERO(pCtx->CmdCtx.Transfers.Callbacks);
     897
     898    pCtx->CmdCtx.Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */
     899    pCtx->CmdCtx.Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT);
     900
     901    pCtx->CmdCtx.Transfers.Callbacks.pfnTransferInitialize = vboxClipboardOnTransferInitCallback;
     902    pCtx->CmdCtx.Transfers.Callbacks.pfnTransferStart      = vboxClipboardOnTransferStartCallback;
     903    pCtx->CmdCtx.Transfers.Callbacks.pfnTransferComplete   = vboxClipboardOnTransferCompleteCallback;
     904    pCtx->CmdCtx.Transfers.Callbacks.pfnTransferError      = vboxClipboardOnTransferErrorCallback;
    824905#endif
    825906
    826907    if (RT_SUCCESS(rc))
    827908    {
    828         /* Check if new Clipboard API is available. */
    829909        rc = SharedClipboardWinCtxInit(&pCtx->Win);
    830910        if (RT_SUCCESS(rc))
     
    832912        if (RT_SUCCESS(rc))
    833913        {
    834             rc = vboxClipboardCreateWindow(pCtx);
     914#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     915            rc = SharedClipboardTransferCtxInit(&pCtx->TransferCtx);
     916#endif
    835917            if (RT_SUCCESS(rc))
    836918            {
    837 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    838                 rc = SharedClipboardTransferCtxInit(&pCtx->TransferCtx);
     919                /* Message pump thread for our proxy window. */
     920                rc = RTThreadCreate(&pCtx->hThread, vboxClipboardWindowThread, pCtx /* pvUser */,
     921                                    0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
     922                                    "shclwnd");
    839923                if (RT_SUCCESS(rc))
    840 #endif
    841                     *ppInstance = pCtx;
     924                {
     925                    int rc2 = RTThreadUserWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */);
     926                    AssertRC(rc2);
     927
     928                    if (!pCtx->fStarted) /* Did the thread fail to start? */
     929                        rc = VERR_NOT_SUPPORTED; /* Report back Shared Clipboard as not being supported. */
     930                }
     931            }
     932
     933            if (RT_SUCCESS(rc))
     934            {
     935                *ppInstance = pCtx;
    842936            }
    843937            else
    844             {
    845938                VbglR3ClipboardDisconnectEx(&pCtx->CmdCtx);
    846             }
    847         }
    848     }
     939        }
     940    }
     941
     942    if (RT_FAILURE(rc))
     943        LogRel(("Shared Clipboard: Unable to initialize, rc=%Rrc\n", rc));
    849944
    850945    LogFlowFuncLeaveRC(rc);
     
    856951    AssertPtr(pInstance);
    857952    LogFlowFunc(("pInstance=%p\n", pInstance));
    858 
    859     HRESULT hr = OleInitialize(NULL);
    860     if (FAILED(hr))
    861     {
    862         LogRel(("Shared Clipboard: Initializing OLE in worker thread failed (%Rhrc) -- file transfers unavailable\n", hr));
    863         /* Not critical, the rest of the clipboard might work. */
    864     }
    865953
    866954    /*
     
    875963    const PSHCLWINCTX pWinCtx = &pCtx->Win;
    876964
     965    LogRel2(("Shared Clipboard: Worker loop running, using protocol v%RU32\n", pCtx->CmdCtx.uProtocolVer));
     966
     967#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     968    HRESULT hr = OleInitialize(NULL);
     969    if (FAILED(hr))
     970    {
     971        LogRel(("Shared Clipboard: Initializing OLE in worker thread failed (%Rhrc) -- file transfers unavailable\n", hr));
     972        /* Not critical, the rest of the clipboard might work. */
     973    }
     974    else
     975        LogRel(("Shared Clipboard: Initialized OLE in worker thraed\n"));
     976#endif
     977
    877978    int rc;
    878979
    879     LogFlowFunc(("Using protocol %RU32\n", pCtx->CmdCtx.uProtocolVer));
     980    LogFlowFunc(("uProtocolVer=%RU32\n", pCtx->CmdCtx.uProtocolVer));
    880981
    881982    uint32_t uMsg;
     
    9461047        if (RT_FAILURE(rc))
    9471048        {
     1049            LogFlowFunc(("Getting next event failed with %Rrc\n", rc));
     1050
    9481051            VbglR3ClipboardEventFree(pEvent);
    9491052            pEvent = NULL;
     
    9871090                case VBGLR3CLIPBOARDEVENTTYPE_QUIT:
    9881091                {
    989                     /* The host is terminating. */
    990                     LogRel(("Shared Clipboard: Terminating ...\n"));
     1092                    LogRel2(("Shared Clipboard: Host requested termination\n"));
    9911093                    ASMAtomicXchgBool(pfShutdown, true);
    9921094                    break;
     
    9941096
    9951097#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    996                 case VBGLR3CLIPBOARDEVENTTYPE_URI_TRANSFER_STATUS:
     1098                case VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS:
    9971099                {
    9981100                    /* Nothing to do here. */
     1101                    rc = VINF_SUCCESS;
    9991102                    break;
    10001103                }
    10011104#endif
    1002                 case VBGLR3CLIPBOARDEVENTTYPE_INVALID:
     1105                case VBGLR3CLIPBOARDEVENTTYPE_NONE:
     1106                {
     1107                    /* Nothing to do here. */
     1108                    rc = VINF_SUCCESS;
     1109                    break;
     1110                }
     1111
    10031112                default:
    10041113                {
    1005                     /* Wait a bit before retrying. */
    1006                     RTThreadSleep(1000);
    1007 
    1008                     rc = VERR_NOT_SUPPORTED;
    1009                     break;
     1114                    AssertMsgFailedBreakStmt(("Event type %RU32 not implemented\n", pEvent->enmType), rc = VERR_NOT_SUPPORTED);
    10101115                }
    10111116            }
     
    10221127    }
    10231128
     1129    LogRel(("Shared Clipboard: Worker loop ended\n"));
     1130
    10241131#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    10251132    OleSetClipboard(NULL); /* Make sure to flush the clipboard on destruction. */
     
    10601167
    10611168#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    1062     OleSetClipboard(NULL); /* Make sure to flush the clipboard on destruction. */
    1063     OleUninitialize();
    1064 
    10651169    SharedClipboardTransferCtxDestroy(&pCtx->TransferCtx);
    10661170#endif
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