Changeset 100204 in vbox for trunk/src/VBox/Additions/WINNT/VBoxTray
- Timestamp:
- Jun 19, 2023 9:11:37 AM (21 months ago)
- svn:sync-xref-src-repo-rev:
- 157911
- Location:
- trunk/src/VBox/Additions/WINNT/VBoxTray
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
r100090 r100204 93 93 *********************************************************************************************************************************/ 94 94 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 95 static DECLCALLBACK(int) vboxClipboardOnTransferInitCallback(PSHCLTXPROVIDERCTX pCtx); 96 static DECLCALLBACK(int) vboxClipboardOnTransferStartCallback(PSHCLTXPROVIDERCTX pCtx); 97 static DECLCALLBACK(void) vboxClipboardOnTransferCompleteCallback(PSHCLTXPROVIDERCTX pCtx, int rc); 98 static DECLCALLBACK(void) vboxClipboardOnTransferErrorCallback(PSHCLTXPROVIDERCTX pCtx, int rc); 95 static DECLCALLBACK(void) vbtrShClTransferInitializedCallback(PSHCLTXPROVIDERCTX pCtx); 96 static DECLCALLBACK(void) vbtrShClTransferStartedCallback(PSHCLTXPROVIDERCTX pCtx); 97 static DECLCALLBACK(void) vbtrShClTransferErrorCallback(PSHCLTXPROVIDERCTX pCtx, int rc); 99 98 #endif 100 99 … … 108 107 * @param pTransfer Pointer to transfer to cleanup. 109 108 */ 110 static void vb oxClipboardTransferCallbackCleanup(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer)109 static void vbtrShClTransferCallbackCleanup(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer) 111 110 { 112 111 LogFlowFuncEnter(); … … 130 129 } 131 130 132 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnInitialize */ 133 static DECLCALLBACK(int) vboxClipboardOnTransferInitCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 131 /** 132 * Worker for a reading clipboard from the host. 133 * 134 * @thread Main clipboard thread. 135 */ 136 static DECLCALLBACK(int) vbtrShClRequestDataFromSourceCallbackWorker(PSHCLCONTEXT pCtx, 137 SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser) 138 { 139 RT_NOREF(pvUser); 140 141 LogFlowFuncEnter(); 142 143 int rc = VERR_NO_DATA; /* Play safe. */ 144 145 uint32_t cbRead = 0; 146 147 uint32_t cbData = _4K; /** @todo Make this dynamic. */ 148 void *pvData = RTMemAlloc(cbData); 149 if (pvData) 150 { 151 rc = VbglR3ClipboardReadDataEx(&pCtx->CmdCtx, uFmt, pvData, cbData, &cbRead); 152 } 153 else 154 rc = VERR_NO_MEMORY; 155 156 /* 157 * A return value of VINF_BUFFER_OVERFLOW tells us to try again with a 158 * larger buffer. The size of the buffer needed is placed in *pcb. 159 * So we start all over again. 160 */ 161 if (rc == VINF_BUFFER_OVERFLOW) 162 { 163 /* cbRead contains the size required. */ 164 165 cbData = cbRead; 166 pvData = RTMemRealloc(pvData, cbRead); 167 if (pvData) 168 { 169 rc = VbglR3ClipboardReadDataEx(&pCtx->CmdCtx, uFmt, pvData, cbData, &cbRead); 170 if (rc == VINF_BUFFER_OVERFLOW) 171 rc = VERR_BUFFER_OVERFLOW; 172 } 173 else 174 rc = VERR_NO_MEMORY; 175 } 176 177 if (!cbRead) 178 rc = VERR_NO_DATA; 179 180 if (RT_SUCCESS(rc)) 181 { 182 if (ppv) 183 *ppv = pvData; 184 if (pcb) 185 *pcb = cbRead; /* Actual bytes read. */ 186 } 187 else 188 { 189 /* 190 * Catch other errors. This also catches the case in which the buffer was 191 * too small a second time, possibly because the clipboard contents 192 * changed half-way through the operation. Since we can't say whether or 193 * not this is actually an error, we just return size 0. 194 */ 195 RTMemFree(pvData); 196 } 197 198 LogFlowFuncLeaveRC(rc); 199 return rc; 200 } 201 202 /** 203 * @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource 204 * 205 * Called from the IDataObject implementation to request data from the host. 206 * 207 * @thread shclwnd thread. 208 */ 209 DECLCALLBACK(int) vbtrShClRequestDataFromSourceCallback(PSHCLCONTEXT pCtx, 210 SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser) 211 { 212 PRTREQ pReq = NULL; 213 int rc = RTReqQueueCallEx(pCtx->Win.hReqQ, &pReq, SHCL_TIMEOUT_DEFAULT_MS, RTREQFLAGS_IPRT_STATUS, 214 (PFNRT)vbtrShClRequestDataFromSourceCallbackWorker, 5, pCtx, uFmt, ppv, pcb, pvUser); 215 RTReqRelease(pReq); 216 return rc; 217 } 218 219 /** 220 * @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnStart 221 * 222 * Called from VbglR3 (main thread) to notify the IDataObject. 223 * 224 * @thread Clipboard main thread. 225 */ 226 static DECLCALLBACK(void) vbtrShClTransferStartedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 134 227 { 135 228 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 136 229 AssertPtr(pCtx); 137 230 138 LogFlowFunc(("pCtx=%p\n", pCtx)); 139 140 RT_NOREF(pCtx); 141 142 return VINF_SUCCESS; 143 } 144 145 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnStart */ 146 static DECLCALLBACK(int) vboxClipboardOnTransferStartCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx) 231 PSHCLTRANSFER pTransfer = pCbCtx->pTransfer; 232 AssertPtr(pTransfer); 233 234 const SHCLTRANSFERDIR enmDir = ShClTransferGetDir(pTransfer); 235 236 LogFlowFunc(("pCtx=%p, idTransfer=%RU32, enmDir=%RU32\n", pCtx, ShClTransferGetID(pTransfer), enmDir)); 237 238 int rc; 239 240 /* The guest wants to transfer data to the host. */ 241 if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) 242 { 243 rc = SharedClipboardWinTransferGetRootsFromClipboard(&pCtx->Win, pTransfer); 244 } 245 /* The guest wants to transfer data from the host. */ 246 else if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) 247 { 248 rc = RTCritSectEnter(&pCtx->Win.CritSect); 249 if (RT_SUCCESS(rc)) 250 { 251 SharedClipboardWinDataObject *pObj = pCtx->Win.pDataObjInFlight; 252 AssertPtrReturnVoid(pObj); 253 rc = pObj->SetAndStartTransfer(pTransfer); 254 255 pCtx->Win.pDataObjInFlight = NULL; /* Hand off to Windows. */ 256 257 int rc2 = RTCritSectLeave(&pCtx->Win.CritSect); 258 AssertRC(rc2); 259 } 260 } 261 else 262 AssertFailedStmt(rc = VERR_NOT_SUPPORTED); 263 264 if (RT_FAILURE(rc)) 265 LogRel(("Shared Clipboard: Starting transfer failed, rc=%Rrc\n", rc)); 266 267 LogFlowFunc(("LEAVE: idTransfer=%RU32, rc=%Rrc\n", ShClTransferGetID(pTransfer), rc)); 268 } 269 270 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnCompleted */ 271 static DECLCALLBACK(void) vbtrShClTransferCompletedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rcCompletion) 147 272 { 148 273 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 149 274 AssertPtr(pCtx); 150 275 151 PSHCLTRANSFER pTransfer = pCbCtx->pTransfer; 152 AssertPtr(pTransfer); 153 154 const SHCLTRANSFERDIR enmDir = ShClTransferGetDir(pTransfer); 155 156 LogFlowFunc(("pCtx=%p, idTransfer=%RU32, enmDir=%RU32\n", pCtx, ShClTransferGetID(pTransfer), enmDir)); 157 158 int rc; 159 160 /* The guest wants to write local data to the host? */ 161 if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) 162 { 163 rc = SharedClipboardWinGetRoots(&pCtx->Win, pTransfer); 164 } 165 /* The guest wants to read data from a remote source. */ 166 else if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) 167 { 168 /* The IDataObject *must* be created on the same thread as our (proxy) window, so post a message to it 169 * to do the stuff for us. */ 170 PSHCLEVENT pEvent; 171 rc = ShClEventSourceGenerateAndRegisterEvent(&pTransfer->Events, &pEvent); 172 if (RT_SUCCESS(rc)) 173 { 174 /* Don't want to rely on SendMessage (synchronous) here, so just post and wait the event getting signalled. */ 175 ::PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_TRANSFER_START, (WPARAM)pTransfer, (LPARAM)pEvent->idEvent); 176 177 PSHCLEVENTPAYLOAD pPayload; 178 rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload); 179 if (RT_SUCCESS(rc)) 180 { 181 Assert(pPayload->cbData == sizeof(int)); 182 rc = *(int *)pPayload->pvData; 183 184 ShClPayloadFree(pPayload); 185 } 186 187 ShClEventRelease(pEvent); 188 } 189 else 190 AssertFailedStmt(rc = VERR_SHCLPB_MAX_EVENTS_REACHED); 191 } 192 else 193 AssertFailedStmt(rc = VERR_NOT_SUPPORTED); 194 195 if (RT_FAILURE(rc)) 196 LogRel(("Shared Clipboard: Starting transfer failed, rc=%Rrc\n", rc)); 197 198 LogFlowFunc(("LEAVE: idTransfer=%RU32, rc=%Rrc\n", ShClTransferGetID(pTransfer), rc)); 199 return rc; 200 } 201 202 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnCompleted */ 203 static DECLCALLBACK(void) vboxClipboardOnTransferCompletedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rcCompletion) 276 LogRel2(("Shared Clipboard: Transfer to destination %s\n", 277 rcCompletion == VERR_CANCELLED ? "canceled" : "complete")); 278 279 vbtrShClTransferCallbackCleanup(&pCtx->TransferCtx, pCbCtx->pTransfer); 280 } 281 282 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnError */ 283 static DECLCALLBACK(void) vbtrShClTransferErrorCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rcError) 204 284 { 205 285 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser; 206 286 AssertPtr(pCtx); 207 287 208 LogRel2(("Shared Clipboard: Transfer to destination %s\n",209 rcCompletion == VERR_CANCELLED ? "canceled" : "complete"));210 211 vboxClipboardTransferCallbackCleanup(&pCtx->TransferCtx, pCbCtx->pTransfer);212 }213 214 /** @copydoc SHCLTRANSFERCALLBACKTABLE::pfnOnError */215 static DECLCALLBACK(void) vboxClipboardOnTransferErrorCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rcError)216 {217 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;218 AssertPtr(pCtx);219 220 288 LogRel(("Shared Clipboard: Transfer to destination failed with %Rrc\n", rcError)); 221 289 222 vb oxClipboardTransferCallbackCleanup(&pCtx->TransferCtx, pCbCtx->pTransfer);290 vbtrShClTransferCallbackCleanup(&pCtx->TransferCtx, pCbCtx->pTransfer); 223 291 } 224 292 225 293 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 226 294 227 static LRESULT vb oxClipboardWinProcessMsg(PSHCLCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)295 static LRESULT vbtrShClWndProcWorker(PSHCLCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 228 296 { 229 297 AssertPtr(pCtx); … … 335 403 } 336 404 337 case WM_RENDERFORMAT: 405 case WM_RENDERFORMAT: /* Guest wants to render the clipboard data. */ 338 406 { 339 407 LogFunc(("WM_RENDERFORMAT\n")); … … 346 414 LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat)); 347 415 416 #ifdef LOG_ENABLED 417 char *pszFmts = ShClFormatsToStrA(fFormat); 418 AssertPtrReturn(pszFmts, 0); 419 LogRel(("Shared Clipboard: Rendering Windows format %#x as VBox format '%s'\n", cfFormat, pszFmts)); 420 RTStrFree(pszFmts); 421 #endif 348 422 if (fFormat == VBOX_SHCL_FMT_NONE) 349 423 { 350 Log Func(("WM_RENDERFORMAT: Unsupported format requested\n"));424 LogRel(("Shared Clipboard: Unsupported format (%#x) requested\n", cfFormat)); 351 425 SharedClipboardWinClear(); 352 426 } … … 535 609 } 536 610 537 case SHCL_WIN_WM_REPORT_FORMATS: 611 case SHCL_WIN_WM_REPORT_FORMATS: /* Host reported clipboard formats. */ 538 612 { 539 613 LogFunc(("SHCL_WIN_WM_REPORT_FORMATS\n")); … … 546 620 const SHCLFORMATS fFormats = pEvent->u.fReportedFormats; 547 621 622 #ifdef LOG_ENABLED 623 char *pszFmts = ShClFormatsToStrA(fFormats); 624 AssertPtrReturn(pszFmts, 0); 625 LogRel(("Shared Clipboard: Host reported formats '%s'\n", pszFmts)); 626 RTStrFree(pszFmts); 627 #endif 548 628 if (fFormats != VBOX_SHCL_FMT_NONE) /* Could arrive with some older GA versions. */ 549 629 { 550 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 551 if (fFormats & VBOX_SHCL_FMT_URI_LIST) 552 {553 LogFunc(("VBOX_SHCL_FMT_URI_LIST\n"));554 630 int rc = SharedClipboardWinClearAndAnnounceFormats(pWinCtx, fFormats, hwnd); 631 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 632 if ( RT_SUCCESS(rc) 633 && fFormats & VBOX_SHCL_FMT_URI_LIST) 634 { 555 635 /* 556 636 * Creating and starting the actual transfer will be done in vbglR3ClipboardTransferStart() as soon … … 558 638 * Transfers always are controlled and initiated on the host side! 559 639 * 560 * So don't announce the transfer to the OS here yet. Don't touch the clipboard in any way here; otherwise561 * this will trigger a WM_DRAWCLIPBOARD or friends, which will result in fun bugs coming up.640 * What we need to do here, however, is, that we create our IDataObject implementation and push it to the 641 * Windows clibpoard. That way Windows will recognize that there is a data transfer "in flight". 562 642 */ 563 } 564 else 565 { 566 #endif 567 SharedClipboardWinClearAndAnnounceFormats(pWinCtx, fFormats, hwnd); 568 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 643 SHCLCALLBACKS Callbacks; 644 RT_ZERO(Callbacks); 645 Callbacks.pfnOnRequestDataFromSource = vbtrShClRequestDataFromSourceCallback; 646 647 rc = SharedClipboardWinTransferCreateAndSetDataObject(pWinCtx, pCtx, &Callbacks); 569 648 } 570 649 #endif … … 575 654 } 576 655 577 case SHCL_WIN_WM_READ_DATA: 656 case SHCL_WIN_WM_READ_DATA: /* Host wants to read clipboard data from the guest. */ 578 657 { 579 658 /* Send data in the specified format to the host. */ … … 585 664 586 665 LogFlowFunc(("SHCL_WIN_WM_READ_DATA: fFormat=%#x\n", fFormat)); 587 666 #ifdef LOG_ENABLED 667 char *pszFmts = ShClFormatsToStrA(fFormat); 668 AssertPtrReturn(pszFmts, 0); 669 LogRel(("Shared Clipboard: Sending data to host as '%s'\n", pszFmts)); 670 RTStrFree(pszFmts); 671 #endif 588 672 int rc = SharedClipboardWinOpen(hwnd); 589 673 HANDLE hClip = NULL; … … 673 757 } 674 758 675 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS676 case SHCL_WIN_WM_TRANSFER_START:677 {678 LogFunc(("SHCL_WIN_WM_TRANSFER_START\n"));679 680 PSHCLTRANSFER pTransfer = (PSHCLTRANSFER)wParam;681 AssertPtr(pTransfer);682 683 const SHCLEVENTID idEvent = (SHCLEVENTID)lParam;684 685 Assert(ShClTransferGetSource(pTransfer) == SHCLSOURCE_REMOTE); /* Sanity. */686 687 int rcTransfer = SharedClipboardWinTransferCreate(pWinCtx, pTransfer);688 689 PSHCLEVENTPAYLOAD pPayload = NULL;690 int rc = ShClPayloadAlloc(idEvent, &rcTransfer, sizeof(rcTransfer), &pPayload);691 if (RT_SUCCESS(rc))692 {693 rc = ShClEventSignal(&pTransfer->Events, idEvent, pPayload);694 if (RT_FAILURE(rc))695 ShClPayloadFree(pPayload);696 }697 698 break;699 }700 #endif701 759 case WM_DESTROY: 702 760 { … … 726 784 } 727 785 728 static LRESULT CALLBACK vb oxClipboardWinWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);729 730 static int vb oxClipboardCreateWindow(PSHCLCONTEXT pCtx)786 static LRESULT CALLBACK vbtrShClWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 787 788 static int vbtrShClCreateWindow(PSHCLCONTEXT pCtx) 731 789 { 732 790 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 747 805 { 748 806 wc.style = CS_NOCLOSE; 749 wc.lpfnWndProc = vb oxClipboardWinWndProc;807 wc.lpfnWndProc = vbtrShClWndProc; 750 808 wc.hInstance = pCtx->pEnv->hInstance; 751 809 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1); … … 788 846 } 789 847 790 static DECLCALLBACK(int) vb oxClipboardWindowThread(RTTHREAD hThread, void *pvUser)848 static DECLCALLBACK(int) vbtrShClWindowThread(RTTHREAD hThread, void *pvUser) 791 849 { 792 850 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pvUser; … … 802 860 else 803 861 LogRel(("Shared Clipboard: Initialized OLE in window thread\n")); 804 #endif 805 806 int rc = vb oxClipboardCreateWindow(pCtx);862 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 863 864 int rc = vbtrShClCreateWindow(pCtx); 807 865 if (RT_FAILURE(rc)) 808 866 { … … 855 913 } 856 914 857 static void vboxClipboardDestroy(PSHCLCONTEXT pCtx) 858 { 915 static LRESULT CALLBACK vbtrShClWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 916 { 917 PSHCLCONTEXT pCtx = &g_Ctx; /** @todo r=andy Make pCtx available through SetWindowLongPtr() / GWL_USERDATA. */ 918 AssertPtr(pCtx); 919 920 /* Forward with proper context. */ 921 return vbtrShClWndProcWorker(pCtx, hWnd, uMsg, wParam, lParam); 922 } 923 924 DECLCALLBACK(int) vbtrShClInit(const PVBOXSERVICEENV pEnv, void **ppInstance) 925 { 926 LogFlowFuncEnter(); 927 928 PSHCLCONTEXT pCtx = &g_Ctx; /* Only one instance for now. */ 929 AssertPtr(pCtx); 930 931 if (pCtx->pEnv) 932 { 933 /* Clipboard was already initialized. 2 or more instances are not supported. */ 934 return VERR_NOT_SUPPORTED; 935 } 936 937 if (VbglR3AutoLogonIsRemoteSession()) 938 { 939 /* Do not use clipboard for remote sessions. */ 940 LogRel(("Shared Clipboard: Clipboard has been disabled for a remote session\n")); 941 return VERR_NOT_SUPPORTED; 942 } 943 944 pCtx->pEnv = pEnv; 945 pCtx->hThread = NIL_RTTHREAD; 946 pCtx->fStarted = false; 947 pCtx->fShutdown = false; 948 949 int rc = RTReqQueueCreate(&pCtx->Win.hReqQ); 950 AssertRCReturn(rc, rc); 951 952 rc = SharedClipboardWinCtxInit(&pCtx->Win); 953 if (RT_SUCCESS(rc)) 954 rc = VbglR3ClipboardConnectEx(&pCtx->CmdCtx, VBOX_SHCL_GF_0_CONTEXT_ID); 955 if (RT_SUCCESS(rc)) 956 { 957 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 958 rc = ShClTransferCtxInit(&pCtx->TransferCtx); 959 #endif 960 if (RT_SUCCESS(rc)) 961 { 962 /* Message pump thread for our proxy window. */ 963 rc = RTThreadCreate(&pCtx->hThread, vbtrShClWindowThread, pCtx /* pvUser */, 964 0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, 965 "shclwnd"); 966 if (RT_SUCCESS(rc)) 967 { 968 int rc2 = RTThreadUserWait(pCtx->hThread, RT_MS_30SEC /* Timeout in ms */); 969 AssertRC(rc2); 970 971 if (!pCtx->fStarted) /* Did the thread fail to start? */ 972 rc = VERR_NOT_SUPPORTED; /* Report back Shared Clipboard as not being supported. */ 973 } 974 } 975 976 if (RT_SUCCESS(rc)) 977 { 978 *ppInstance = pCtx; 979 } 980 else 981 VbglR3ClipboardDisconnectEx(&pCtx->CmdCtx); 982 } 983 984 if (RT_FAILURE(rc)) 985 LogRel(("Shared Clipboard: Unable to initialize, rc=%Rrc\n", rc)); 986 987 LogFlowFuncLeaveRC(rc); 988 return rc; 989 } 990 991 DECLCALLBACK(int) vbtrShClWorker(void *pInstance, bool volatile *pfShutdown) 992 { 993 AssertPtr(pInstance); 994 LogFlowFunc(("pInstance=%p\n", pInstance)); 995 996 /* 997 * Tell the control thread that it can continue 998 * spawning services. 999 */ 1000 RTThreadUserSignal(RTThreadSelf()); 1001 1002 const PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pInstance; 1003 AssertPtr(pCtx); 1004 1005 const PSHCLWINCTX pWinCtx = &pCtx->Win; 1006 1007 LogRel2(("Shared Clipboard: Worker loop running\n")); 1008 1009 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1010 HRESULT hr = OleInitialize(NULL); 1011 if (FAILED(hr)) 1012 { 1013 LogRel(("Shared Clipboard: Initializing OLE in worker thread failed (%Rhrc) -- file transfers unavailable\n", hr)); 1014 /* Not critical, the rest of the clipboard might work. */ 1015 } 1016 else 1017 LogRel(("Shared Clipboard: Initialized OLE in worker thread\n")); 1018 1019 /* 1020 * Init callbacks. 1021 * Those will be registered within VbglR3 when a new transfer gets initialized. 1022 */ 1023 RT_ZERO(pCtx->CmdCtx.Transfers.Callbacks); 1024 1025 pCtx->CmdCtx.Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */ 1026 pCtx->CmdCtx.Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT); 1027 1028 pCtx->CmdCtx.Transfers.Callbacks.pfnOnStarted = vbtrShClTransferStartedCallback; 1029 pCtx->CmdCtx.Transfers.Callbacks.pfnOnCompleted = vbtrShClTransferCompletedCallback; 1030 pCtx->CmdCtx.Transfers.Callbacks.pfnOnError = vbtrShClTransferErrorCallback; 1031 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ 1032 1033 int rc; 1034 1035 /* The thread waits for incoming messages from the host. */ 1036 PVBGLR3CLIPBOARDEVENT pEvent = NULL; 1037 for (;;) 1038 { 1039 LogFlowFunc(("Waiting for host message (fUseLegacyProtocol=%RTbool, fHostFeatures=%#RX64) ...\n", 1040 pCtx->CmdCtx.fUseLegacyProtocol, pCtx->CmdCtx.fHostFeatures)); 1041 1042 if (!pEvent) 1043 pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT)); 1044 AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY); 1045 1046 uint32_t idMsg = 0; 1047 uint32_t cParms = 0; 1048 rc = VbglR3ClipboardMsgPeek(&pCtx->CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */); 1049 if (RT_SUCCESS(rc)) 1050 { 1051 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1052 rc = VbglR3ClipboardEventGetNextEx(idMsg, cParms, &pCtx->CmdCtx, &pCtx->TransferCtx, pEvent); 1053 #else 1054 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, &pCtx->CmdCtx, pEvent); 1055 #endif 1056 } 1057 else if (rc == VERR_TRY_AGAIN) /* No new message (yet). */ 1058 { 1059 RTReqQueueProcess(pCtx->Win.hReqQ, RT_MS_1SEC); 1060 continue; 1061 } 1062 1063 if (RT_FAILURE(rc)) 1064 { 1065 LogFlowFunc(("Getting next event failed with %Rrc\n", rc)); 1066 1067 VbglR3ClipboardEventFree(pEvent); 1068 pEvent = NULL; 1069 1070 if (*pfShutdown) 1071 break; 1072 1073 /* Wait a bit before retrying. */ 1074 RTThreadSleep(1000); 1075 continue; 1076 } 1077 else 1078 { 1079 AssertPtr(pEvent); 1080 LogFlowFunc(("Event uType=%RU32\n", pEvent->enmType)); 1081 1082 switch (pEvent->enmType) 1083 { 1084 case VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS: 1085 { 1086 /* The host has announced available clipboard formats. 1087 * Forward the information to the window, so it can later 1088 * respond to WM_RENDERFORMAT message. */ 1089 ::PostMessage(pWinCtx->hWnd, SHCL_WIN_WM_REPORT_FORMATS, 1090 0 /* wParam */, (LPARAM)pEvent /* lParam */); 1091 1092 pEvent = NULL; /* Consume pointer. */ 1093 break; 1094 } 1095 1096 case VBGLR3CLIPBOARDEVENTTYPE_READ_DATA: 1097 { 1098 /* The host needs data in the specified format. */ 1099 ::PostMessage(pWinCtx->hWnd, SHCL_WIN_WM_READ_DATA, 1100 0 /* wParam */, (LPARAM)pEvent /* lParam */); 1101 1102 pEvent = NULL; /* Consume pointer. */ 1103 break; 1104 } 1105 1106 case VBGLR3CLIPBOARDEVENTTYPE_QUIT: 1107 { 1108 LogRel2(("Shared Clipboard: Host requested termination\n")); 1109 ASMAtomicXchgBool(pfShutdown, true); 1110 break; 1111 } 1112 1113 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1114 case VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS: 1115 { 1116 /* Nothing to do here. */ 1117 rc = VINF_SUCCESS; 1118 break; 1119 } 1120 #endif 1121 case VBGLR3CLIPBOARDEVENTTYPE_NONE: 1122 { 1123 /* Nothing to do here. */ 1124 rc = VINF_SUCCESS; 1125 break; 1126 } 1127 1128 default: 1129 { 1130 AssertMsgFailedBreakStmt(("Event type %RU32 not implemented\n", pEvent->enmType), rc = VERR_NOT_SUPPORTED); 1131 } 1132 } 1133 1134 if (pEvent) 1135 { 1136 VbglR3ClipboardEventFree(pEvent); 1137 pEvent = NULL; 1138 } 1139 } 1140 1141 if (*pfShutdown) 1142 break; 1143 } 1144 1145 LogRel2(("Shared Clipboard: Worker loop ended\n")); 1146 1147 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1148 OleSetClipboard(NULL); /* Make sure to flush the clipboard on destruction. */ 1149 OleUninitialize(); 1150 #endif 1151 1152 LogFlowFuncLeaveRC(rc); 1153 return rc; 1154 } 1155 1156 DECLCALLBACK(int) vbtrShClStop(void *pInstance) 1157 { 1158 AssertPtrReturn(pInstance, VERR_INVALID_POINTER); 1159 1160 LogFunc(("Stopping pInstance=%p\n", pInstance)); 1161 1162 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pInstance; 1163 AssertPtr(pCtx); 1164 1165 /* Set shutdown indicator. */ 1166 ASMAtomicWriteBool(&pCtx->fShutdown, true); 1167 1168 /* Let our clipboard know that we're going to shut down. */ 1169 PostMessage(pCtx->Win.hWnd, WM_QUIT, 0, 0); 1170 1171 /* Disconnect from the host service. 1172 * This will also send a VBOX_SHCL_HOST_MSG_QUIT from the host so that we can break out from our message worker. */ 1173 VbglR3ClipboardDisconnect(pCtx->CmdCtx.idClient); 1174 pCtx->CmdCtx.idClient = 0; 1175 1176 LogFlowFuncLeaveRC(VINF_SUCCESS); 1177 return VINF_SUCCESS; 1178 } 1179 1180 DECLCALLBACK(void) vbtrShClDestroy(void *pInstance) 1181 { 1182 AssertPtrReturnVoid(pInstance); 1183 1184 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pInstance; 859 1185 AssertPtrReturnVoid(pCtx); 1186 1187 /* Make sure that we are disconnected. */ 1188 Assert(pCtx->CmdCtx.idClient == 0); 860 1189 861 1190 LogFlowFunc(("pCtx=%p\n", pCtx)); … … 884 1213 SharedClipboardWinCtxDestroy(&pCtx->Win); 885 1214 1215 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS 1216 ShClTransferCtxDestroy(&pCtx->TransferCtx); 1217 #endif 1218 1219 RTReqQueueDestroy(pCtx->Win.hReqQ); 1220 886 1221 LogRel2(("Shared Clipboard: Destroyed\n")); 887 }888 889 static LRESULT CALLBACK vboxClipboardWinWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)890 {891 PSHCLCONTEXT pCtx = &g_Ctx; /** @todo r=andy Make pCtx available through SetWindowLongPtr() / GWL_USERDATA. */892 AssertPtr(pCtx);893 894 /* Forward with proper context. */895 return vboxClipboardWinProcessMsg(pCtx, hWnd, uMsg, wParam, lParam);896 }897 898 DECLCALLBACK(int) VBoxShClInit(const PVBOXSERVICEENV pEnv, void **ppInstance)899 {900 LogFlowFuncEnter();901 902 PSHCLCONTEXT pCtx = &g_Ctx; /* Only one instance for now. */903 AssertPtr(pCtx);904 905 if (pCtx->pEnv)906 {907 /* Clipboard was already initialized. 2 or more instances are not supported. */908 return VERR_NOT_SUPPORTED;909 }910 911 if (VbglR3AutoLogonIsRemoteSession())912 {913 /* Do not use clipboard for remote sessions. */914 LogRel(("Shared Clipboard: Clipboard has been disabled for a remote session\n"));915 return VERR_NOT_SUPPORTED;916 }917 918 pCtx->pEnv = pEnv;919 pCtx->hThread = NIL_RTTHREAD;920 pCtx->fStarted = false;921 pCtx->fShutdown = false;922 923 int rc = VINF_SUCCESS;924 925 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS926 /*927 * Set callbacks.928 * Those will be registered within VbglR3 when a new transfer gets initialized.929 */930 RT_ZERO(pCtx->CmdCtx.Transfers.Callbacks);931 932 pCtx->CmdCtx.Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */933 pCtx->CmdCtx.Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT);934 935 pCtx->CmdCtx.Transfers.Callbacks.pfnOnInitialize = vboxClipboardOnTransferInitCallback;936 pCtx->CmdCtx.Transfers.Callbacks.pfnOnStart = vboxClipboardOnTransferStartCallback;937 pCtx->CmdCtx.Transfers.Callbacks.pfnOnCompleted = vboxClipboardOnTransferCompletedCallback;938 pCtx->CmdCtx.Transfers.Callbacks.pfnOnError = vboxClipboardOnTransferErrorCallback;939 #endif940 941 if (RT_SUCCESS(rc))942 {943 rc = SharedClipboardWinCtxInit(&pCtx->Win);944 if (RT_SUCCESS(rc))945 rc = VbglR3ClipboardConnectEx(&pCtx->CmdCtx, VBOX_SHCL_GF_0_CONTEXT_ID);946 if (RT_SUCCESS(rc))947 {948 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS949 rc = ShClTransferCtxInit(&pCtx->TransferCtx);950 #endif951 if (RT_SUCCESS(rc))952 {953 /* Message pump thread for our proxy window. */954 rc = RTThreadCreate(&pCtx->hThread, vboxClipboardWindowThread, pCtx /* pvUser */,955 0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,956 "shclwnd");957 if (RT_SUCCESS(rc))958 {959 int rc2 = RTThreadUserWait(pCtx->hThread, 30 * 1000 /* Timeout in ms */);960 AssertRC(rc2);961 962 if (!pCtx->fStarted) /* Did the thread fail to start? */963 rc = VERR_NOT_SUPPORTED; /* Report back Shared Clipboard as not being supported. */964 }965 }966 967 if (RT_SUCCESS(rc))968 {969 *ppInstance = pCtx;970 }971 else972 VbglR3ClipboardDisconnectEx(&pCtx->CmdCtx);973 }974 }975 976 if (RT_FAILURE(rc))977 LogRel(("Shared Clipboard: Unable to initialize, rc=%Rrc\n", rc));978 979 LogFlowFuncLeaveRC(rc);980 return rc;981 }982 983 DECLCALLBACK(int) VBoxShClWorker(void *pInstance, bool volatile *pfShutdown)984 {985 AssertPtr(pInstance);986 LogFlowFunc(("pInstance=%p\n", pInstance));987 988 /*989 * Tell the control thread that it can continue990 * spawning services.991 */992 RTThreadUserSignal(RTThreadSelf());993 994 const PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pInstance;995 AssertPtr(pCtx);996 997 const PSHCLWINCTX pWinCtx = &pCtx->Win;998 999 LogRel2(("Shared Clipboard: Worker loop running\n"));1000 1001 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS1002 HRESULT hr = OleInitialize(NULL);1003 if (FAILED(hr))1004 {1005 LogRel(("Shared Clipboard: Initializing OLE in worker thread failed (%Rhrc) -- file transfers unavailable\n", hr));1006 /* Not critical, the rest of the clipboard might work. */1007 }1008 else1009 LogRel(("Shared Clipboard: Initialized OLE in worker thread\n"));1010 #endif1011 1012 int rc;1013 1014 /* The thread waits for incoming messages from the host. */1015 for (;;)1016 {1017 LogFlowFunc(("Waiting for host message (fUseLegacyProtocol=%RTbool, fHostFeatures=%#RX64) ...\n",1018 pCtx->CmdCtx.fUseLegacyProtocol, pCtx->CmdCtx.fHostFeatures));1019 1020 PVBGLR3CLIPBOARDEVENT pEvent = (PVBGLR3CLIPBOARDEVENT)RTMemAllocZ(sizeof(VBGLR3CLIPBOARDEVENT));1021 AssertPtrBreakStmt(pEvent, rc = VERR_NO_MEMORY);1022 1023 uint32_t idMsg = 0;1024 uint32_t cParms = 0;1025 rc = VbglR3ClipboardMsgPeekWait(&pCtx->CmdCtx, &idMsg, &cParms, NULL /* pidRestoreCheck */);1026 if (RT_SUCCESS(rc))1027 {1028 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS1029 rc = VbglR3ClipboardEventGetNextEx(idMsg, cParms, &pCtx->CmdCtx, &pCtx->TransferCtx, pEvent);1030 #else1031 rc = VbglR3ClipboardEventGetNext(idMsg, cParms, &pCtx->CmdCtx, pEvent);1032 #endif1033 }1034 1035 if (RT_FAILURE(rc))1036 {1037 LogFlowFunc(("Getting next event failed with %Rrc\n", rc));1038 1039 VbglR3ClipboardEventFree(pEvent);1040 pEvent = NULL;1041 1042 if (*pfShutdown)1043 break;1044 1045 /* Wait a bit before retrying. */1046 RTThreadSleep(1000);1047 continue;1048 }1049 else1050 {1051 AssertPtr(pEvent);1052 LogFlowFunc(("Event uType=%RU32\n", pEvent->enmType));1053 1054 switch (pEvent->enmType)1055 {1056 case VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS:1057 {1058 /* The host has announced available clipboard formats.1059 * Forward the information to the window, so it can later1060 * respond to WM_RENDERFORMAT message. */1061 ::PostMessage(pWinCtx->hWnd, SHCL_WIN_WM_REPORT_FORMATS,1062 0 /* wParam */, (LPARAM)pEvent /* lParam */);1063 1064 pEvent = NULL; /* Consume pointer. */1065 break;1066 }1067 1068 case VBGLR3CLIPBOARDEVENTTYPE_READ_DATA:1069 {1070 /* The host needs data in the specified format. */1071 ::PostMessage(pWinCtx->hWnd, SHCL_WIN_WM_READ_DATA,1072 0 /* wParam */, (LPARAM)pEvent /* lParam */);1073 1074 pEvent = NULL; /* Consume pointer. */1075 break;1076 }1077 1078 case VBGLR3CLIPBOARDEVENTTYPE_QUIT:1079 {1080 LogRel2(("Shared Clipboard: Host requested termination\n"));1081 ASMAtomicXchgBool(pfShutdown, true);1082 break;1083 }1084 1085 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS1086 case VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS:1087 {1088 /* Nothing to do here. */1089 rc = VINF_SUCCESS;1090 break;1091 }1092 #endif1093 case VBGLR3CLIPBOARDEVENTTYPE_NONE:1094 {1095 /* Nothing to do here. */1096 rc = VINF_SUCCESS;1097 break;1098 }1099 1100 default:1101 {1102 AssertMsgFailedBreakStmt(("Event type %RU32 not implemented\n", pEvent->enmType), rc = VERR_NOT_SUPPORTED);1103 }1104 }1105 1106 if (pEvent)1107 {1108 VbglR3ClipboardEventFree(pEvent);1109 pEvent = NULL;1110 }1111 }1112 1113 if (*pfShutdown)1114 break;1115 }1116 1117 LogRel2(("Shared Clipboard: Worker loop ended\n"));1118 1119 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS1120 OleSetClipboard(NULL); /* Make sure to flush the clipboard on destruction. */1121 OleUninitialize();1122 #endif1123 1124 LogFlowFuncLeaveRC(rc);1125 return rc;1126 }1127 1128 DECLCALLBACK(int) VBoxShClStop(void *pInstance)1129 {1130 AssertPtrReturn(pInstance, VERR_INVALID_POINTER);1131 1132 LogFunc(("Stopping pInstance=%p\n", pInstance));1133 1134 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pInstance;1135 AssertPtr(pCtx);1136 1137 /* Set shutdown indicator. */1138 ASMAtomicWriteBool(&pCtx->fShutdown, true);1139 1140 /* Let our clipboard know that we're going to shut down. */1141 PostMessage(pCtx->Win.hWnd, WM_QUIT, 0, 0);1142 1143 /* Disconnect from the host service.1144 * This will also send a VBOX_SHCL_HOST_MSG_QUIT from the host so that we can break out from our message worker. */1145 VbglR3ClipboardDisconnect(pCtx->CmdCtx.idClient);1146 pCtx->CmdCtx.idClient = 0;1147 1148 LogFlowFuncLeaveRC(VINF_SUCCESS);1149 return VINF_SUCCESS;1150 }1151 1152 DECLCALLBACK(void) VBoxShClDestroy(void *pInstance)1153 {1154 AssertPtrReturnVoid(pInstance);1155 1156 PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pInstance;1157 AssertPtr(pCtx);1158 1159 /* Make sure that we are disconnected. */1160 Assert(pCtx->CmdCtx.idClient == 0);1161 1162 vboxClipboardDestroy(pCtx);1163 1164 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS1165 ShClTransferCtxDestroy(&pCtx->TransferCtx);1166 #endif1167 1222 1168 1223 return; … … 1179 1234 "Shared Clipboard", 1180 1235 /* methods */ 1181 VBoxShClInit,1182 VBoxShClWorker,1183 VBoxShClStop,1184 VBoxShClDestroy1236 vbtrShClInit, 1237 vbtrShClWorker, 1238 vbtrShClStop, 1239 vbtrShClDestroy 1185 1240 }; -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp
r99739 r100204 98 98 static VBOXSERVICEINFO g_aServices[] = 99 99 { 100 { &g_SvcDescDnD, NIL_RTTHREAD, NULL, false, false, false, false, true }100 { &g_SvcDescClipboard, NIL_RTTHREAD, NULL, false, false, false, false, true } 101 101 }; 102 102 #else … … 533 533 RTLogSetDefaultInstance(g_pLoggerRelease); 534 534 535 const char *apszGroups[] = { "all", "guest_dnd" }; /* All groups we want to enable logging for VBoxTray. */ 535 /* All groups we want to enable logging for VBoxTray. */ 536 const char *apszGroups[] = { "guest_dnd", "shared_clipboard" }; 536 537 char szGroupSettings[_1K]; 537 538
Note:
See TracChangeset
for help on using the changeset viewer.