Changeset 78151 in vbox
- Timestamp:
- Apr 17, 2019 12:03:42 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 8 edited
-
include/VBox/GuestHost/SharedClipboard-win.h (added)
-
include/VBox/GuestHost/SharedClipboard.h (modified) (2 diffs)
-
include/VBox/HostServices/VBoxClipboardSvc.h (modified) (2 diffs)
-
src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk (modified) (2 diffs)
-
src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp (modified) (27 diffs)
-
src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp (added)
-
src/VBox/HostServices/SharedClipboard/Makefile.kmk (modified) (1 diff)
-
src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp (modified) (39 diffs)
-
src/VBox/HostServices/SharedClipboard/VBoxClipboard.h (modified) (3 diffs)
-
src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/SharedClipboard.h
r76585 r78151 33 33 #include <iprt/types.h> 34 34 35 /** 36 * Supported data formats for Shared Clipboard. Bit mask. 37 */ 38 /** Shared Clipboard format is an Unicode text. */ 39 #define VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT UINT32_C(0x01) 40 /** Shared Clipboard format is bitmap (BMP / DIB). */ 41 #define VBOX_SHARED_CLIPBOARD_FMT_BITMAP UINT32_C(0x02) 42 /** Shared Clipboard format is HTML. */ 43 #define VBOX_SHARED_CLIPBOARD_FMT_HTML UINT32_C(0x04) 44 45 /** 46 * The host messages for the guest. 47 */ 48 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT 1 49 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA 2 50 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS 3 51 35 52 enum 36 53 { … … 46 63 struct _VBOXCLIPBOARDCONTEXT; 47 64 typedef struct _VBOXCLIPBOARDCONTEXT VBOXCLIPBOARDCONTEXT; 65 typedef struct _VBOXCLIPBOARDCONTEXT *PVBOXCLIPBOARDCONTEXT; 48 66 49 67 /** Opaque data structure for the X11/VBox backend code. */ -
trunk/include/VBox/HostServices/VBoxClipboardSvc.h
r76585 r78151 43 43 44 44 /* 45 * Supported data formats. Bit mask.46 */47 #define VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT UINT32_C(0x01)48 #define VBOX_SHARED_CLIPBOARD_FMT_BITMAP UINT32_C(0x02)49 #define VBOX_SHARED_CLIPBOARD_FMT_HTML UINT32_C(0x04)50 51 /*52 45 * The service functions which are callable by host. 53 46 */ … … 67 60 /* Send data in requested format to host. */ 68 61 #define VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA 4 69 70 /*71 * The host messages for the guest.72 */73 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT 174 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA 275 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS 376 62 77 63 /* -
trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
r76553 r78151 37 37 VBoxDispIf.cpp \ 38 38 VBoxSeamless.cpp \ 39 VBoxClipboard.cpp \40 39 VBoxDisplay.cpp \ 41 40 VBoxVRDP.cpp \ … … 46 45 VBoxTray_VBOX_IMPORT_CHECKER.win.x86 = nt4 #nt350 47 46 VBoxTray_VBOX_IMPORT_CHECKER.win.amd64 = xp64 47 ifdef VBOX_WITH_SHARED_CLIPBOARD 48 VBoxTray_DEFS += \ 49 VBOX_WITH_SHARED_CLIPBOARD 50 VBoxTray_SOURCES += \ 51 VBoxClipboard.cpp \ 52 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp 53 endif 48 54 ifdef VBOX_WITH_DRAG_AND_DROP 49 55 VBoxTray_DEFS += \ -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
r78142 r78151 27 27 #include <iprt/ldr.h> 28 28 29 #include <VBox/HostServices/VBoxClipboardSvc.h> 29 #include <VBox/GuestHost/SharedClipboard.h> 30 #include <VBox/GuestHost/SharedClipboard-win.h> 30 31 #include <strsafe.h> 31 32 … … 36 37 * Structures and Typedefs * 37 38 *********************************************************************************************************************************/ 38 /* Dynamically load clipboard functions from User32.dll. */ 39 typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND); 40 typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER; 41 42 typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND); 43 typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER; 44 45 #ifndef WM_CLIPBOARDUPDATE 46 #define WM_CLIPBOARDUPDATE 0x031D 47 #endif 48 49 /** Sets announced clipboard formats from the host. */ 50 #define VBOX_WM_SHCLPB_SET_FORMATS WM_USER 51 /** Reads data from the clipboard and sends it to the host. */ 52 #define VBOX_WM_SHCLPB_READ_DATA WM_USER + 1 53 54 typedef struct _VBOXCLIPBOARDCONTEXT 55 { 56 const VBOXSERVICEENV *pEnv; 57 uint32_t u32ClientID; 58 ATOM wndClass; 59 HWND hwnd; 60 HWND hwndNextInChain; 61 UINT timerRefresh; 62 bool fCBChainPingInProcess; 63 PFNADDCLIPBOARDFORMATLISTENER pfnAddClipboardFormatListener; 64 PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener; 65 } VBOXCLIPBOARDCONTEXT, *PVBOXCLIPBOARDCONTEXT; 66 67 enum { CBCHAIN_TIMEOUT = 5000 /* ms */ }; 68 39 40 struct _VBOXCLIPBOARDCONTEXT 41 { 42 /** Pointer to the VBoxClient service environment. */ 43 const VBOXSERVICEENV *pEnv; 44 /** Client ID the service is connected to the HGCM service with. */ 45 uint32_t u32ClientID; 46 /** Windows-specific context data. */ 47 VBOXCLIPBOARDWINCTX Win; 48 }; 69 49 70 50 /********************************************************************************************************************************* 71 * Header Files*51 * Static variables * 72 52 *********************************************************************************************************************************/ 73 /** Static since it is the single instance. Directly used in the windows proc. */53 /** Static clipboard context (since it is the single instance). Directly used in the windows proc. */ 74 54 static VBOXCLIPBOARDCONTEXT g_Ctx = { NULL }; 75 76 static char s_szClipWndClassName[] = "VBoxSharedClipboardClass"; 77 78 79 static void vboxClipboardInitNewAPI(VBOXCLIPBOARDCONTEXT *pCtx) 80 { 81 RTLDRMOD hUser32 = NIL_RTLDRMOD; 82 int rc = RTLdrLoadSystem("User32.dll", /* fNoUnload = */ true, &hUser32); 83 if (RT_SUCCESS(rc)) 84 { 85 rc = RTLdrGetSymbol(hUser32, "AddClipboardFormatListener", (void**)&pCtx->pfnAddClipboardFormatListener); 86 if (RT_SUCCESS(rc)) 87 { 88 rc = RTLdrGetSymbol(hUser32, "RemoveClipboardFormatListener", (void**)&pCtx->pfnRemoveClipboardFormatListener); 89 } 90 91 RTLdrClose(hUser32); 92 } 93 94 if (RT_SUCCESS(rc)) 95 { 96 Log(("New Clipboard API is enabled\n")); 97 } 98 else 99 { 100 pCtx->pfnAddClipboardFormatListener = NULL; 101 pCtx->pfnRemoveClipboardFormatListener = NULL; 102 Log(("New Clipboard API is not available. rc = %Rrc\n", rc)); 103 } 104 } 105 106 static bool vboxClipboardIsNewAPI(VBOXCLIPBOARDCONTEXT *pCtx) 107 { 108 return pCtx->pfnAddClipboardFormatListener != NULL; 109 } 110 111 112 static int vboxOpenClipboard(HWND hWnd) 113 { 114 /* "OpenClipboard fails if another window has the clipboard open." 115 * So try a few times and wait up to 1 second. 116 */ 117 BOOL fOpened = FALSE; 118 119 LogFlowFunc(("hWnd=%p\n", hWnd)); 120 121 int i = 0; 122 for (;;) 123 { 124 if (OpenClipboard(hWnd)) 125 { 126 fOpened = TRUE; 127 break; 128 } 129 130 if (i >= 10) /* sleep interval = [1..512] ms */ 131 break; 132 133 RTThreadSleep(1 << i); 134 ++i; 135 } 136 137 #ifdef LOG_ENABLED 138 if (i > 0) 139 LogFlowFunc(("%d times tried to open clipboard\n", i + 1)); 140 #endif 141 142 int rc; 143 if (fOpened) 144 rc = VINF_SUCCESS; 145 else 146 { 147 const DWORD dwLastErr = GetLastError(); 148 rc = RTErrConvertFromWin32(dwLastErr); 149 LogRel(("Clipboard: Failed to open clipboard! Error=%ld (%Rrc)\n", dwLastErr, rc)); 150 } 151 152 return rc; 153 } 154 155 156 static int vboxClipboardChanged(PVBOXCLIPBOARDCONTEXT pCtx) 55 /** Static window class name. */ 56 static char s_szClipWndClassName[] = VBOX_CLIPBOARD_WNDCLASS_NAME; 57 58 59 static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 157 60 { 158 61 AssertPtr(pCtx); 159 62 160 /* Query list of available formats and report to host. */ 161 int rc = vboxOpenClipboard(pCtx->hwnd); 162 if (RT_SUCCESS(rc)) 163 { 164 uint32_t u32Formats = 0; 165 UINT format = 0; 166 167 while ((format = EnumClipboardFormats(format)) != 0) 168 { 169 LogFlowFunc(("vboxClipboardChanged: format = 0x%08X\n", format)); 170 switch (format) 171 { 172 case CF_UNICODETEXT: 173 case CF_TEXT: 174 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT; 175 break; 176 177 case CF_DIB: 178 case CF_BITMAP: 179 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP; 180 break; 181 182 default: 183 { 184 if (format >= 0xC000) 185 { 186 TCHAR szFormatName[256]; 187 188 int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR)); 189 if (cActual) 190 { 191 if (strcmp (szFormatName, "HTML Format") == 0) 192 { 193 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_HTML; 194 } 195 } 196 } 197 break; 198 } 199 } 200 } 201 202 CloseClipboard(); 203 rc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, u32Formats); 204 } 205 return rc; 206 } 207 208 /* Add ourselves into the chain of cliboard listeners */ 209 static void vboxClipboardAddToCBChain(PVBOXCLIPBOARDCONTEXT pCtx) 210 { 211 AssertPtrReturnVoid(pCtx); 212 if (vboxClipboardIsNewAPI(pCtx)) 213 pCtx->pfnAddClipboardFormatListener(pCtx->hwnd); 214 else 215 pCtx->hwndNextInChain = SetClipboardViewer(pCtx->hwnd); 216 /** @todo r=andy Return code?? */ 217 } 218 219 /* Remove ourselves from the chain of cliboard listeners */ 220 static void vboxClipboardRemoveFromCBChain(PVBOXCLIPBOARDCONTEXT pCtx) 221 { 222 AssertPtrReturnVoid(pCtx); 223 224 if (vboxClipboardIsNewAPI(pCtx)) 225 { 226 pCtx->pfnRemoveClipboardFormatListener(pCtx->hwnd); 227 } 228 else 229 { 230 ChangeClipboardChain(pCtx->hwnd, pCtx->hwndNextInChain); 231 pCtx->hwndNextInChain = NULL; 232 } 233 /** @todo r=andy Return code?? */ 234 } 235 236 /* Callback which is invoked when we have successfully pinged ourselves down the 237 * clipboard chain. We simply unset a boolean flag to say that we are responding. 238 * There is a race if a ping returns after the next one is initiated, but nothing 239 * very bad is likely to happen. */ 240 VOID CALLBACK vboxClipboardChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult) 241 { 242 NOREF(hWnd); 243 NOREF(uMsg); 244 NOREF(lResult); 245 246 /** @todo r=andy Why not using SetWindowLongPtr for keeping the context? */ 247 PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)dwData; 248 AssertPtr(pCtx); 249 250 pCtx->fCBChainPingInProcess = FALSE; 251 } 252 253 static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 254 { 255 AssertPtr(pCtx); 63 const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win; 256 64 257 65 LRESULT rc = 0; … … 266 74 { 267 75 /* Clipboard was updated by another application. */ 268 vboxClipboardChanged(pCtx); 76 uint32_t uFormats; 77 int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats); 78 if (RT_SUCCESS(vboxrc)) 79 vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats); 269 80 } 270 81 } break; … … 272 83 case WM_CHANGECBCHAIN: 273 84 { 274 if ( vboxClipboardIsNewAPI(pCtx))85 if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI)) 275 86 { 276 87 rc = DefWindowProc(hwnd, msg, wParam, lParam); … … 278 89 } 279 90 280 HWND h wndRemoved = (HWND)wParam;281 HWND h wndNext = (HWND)lParam;282 283 LogFlowFunc(("WM_CHANGECBCHAIN: h wndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));284 285 if (h wndRemoved == pCtx->hwndNextInChain)91 HWND hWndRemoved = (HWND)wParam; 92 HWND hWndNext = (HWND)lParam; 93 94 LogFlowFunc(("WM_CHANGECBCHAIN: hWndRemoved=%p, hWndNext=%p, hWnd=%p\n", hWndRemoved, hWndNext, pWinCtx->hWnd)); 95 96 if (hWndRemoved == pWinCtx->hWndNextInChain) 286 97 { 287 98 /* The window that was next to our in the chain is being removed. 288 99 * Relink to the new next window. */ 289 p Ctx->hwndNextInChain = hwndNext;100 pWinCtx->hWndNextInChain = hWndNext; 290 101 } 291 102 else 292 103 { 293 if (p Ctx->hwndNextInChain)104 if (pWinCtx->hWndNextInChain) 294 105 { 295 106 /* Pass the message further. */ 296 107 DWORD_PTR dwResult; 297 rc = SendMessageTimeout(pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult); 108 rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, 109 VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, &dwResult); 298 110 if (!rc) 299 111 rc = (LRESULT) dwResult; … … 304 116 case WM_DRAWCLIPBOARD: 305 117 { 306 LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", p Ctx->hwnd));118 LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd)); 307 119 308 120 if (GetClipboardOwner() != hwnd) … … 310 122 /* Clipboard was updated by another application. */ 311 123 /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */ 312 int vboxrc = vboxClipboardChanged(pCtx); 313 if (RT_FAILURE(vboxrc)) 314 LogFlowFunc(("vboxClipboardChanged failed, rc = %Rrc\n", vboxrc)); 315 } 316 317 if (pCtx->hwndNextInChain) 124 uint32_t uFormats; 125 int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &uFormats); 126 if (RT_SUCCESS(vboxrc)) 127 vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats); 128 } 129 130 if (pWinCtx->hWndNextInChain) 318 131 { 319 132 /* Pass the message to next windows in the clipboard chain. */ 320 SendMessageTimeout(p Ctx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, NULL);133 SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, NULL); 321 134 } 322 135 } break; … … 324 137 case WM_TIMER: 325 138 { 326 if ( vboxClipboardIsNewAPI(pCtx))139 if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI)) 327 140 break; 328 141 … … 331 144 /* Re-register ourselves in the clipboard chain if our last ping 332 145 * timed out or there seems to be no valid chain. */ 333 if (!hViewer || pCtx->fCBChainPingInProcess) 334 { 335 vboxClipboardRemoveFromCBChain(pCtx); 336 vboxClipboardAddToCBChain(pCtx); 337 } 146 if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess) 147 { 148 VBoxClipboardWinRemoveFromCBChain(pWinCtx); 149 VBoxClipboardWinAddToCBChain(pWinCtx); 150 } 151 338 152 /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be 339 153 * processed by ourselves to the chain. */ 340 pCtx->fCBChainPingInProcess = TRUE; 154 pWinCtx->oldAPI.fCBChainPingInProcess = TRUE; 155 341 156 hViewer = GetClipboardViewer(); 342 157 if (hViewer) 343 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, vboxClipboardChainPingProc, (ULONG_PTR)pCtx); 158 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain, 159 VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx); 344 160 } break; 345 161 … … 387 203 /* Unsupported clipboard format is requested. */ 388 204 LogFlowFunc(("Unsupported clipboard format requested: %ld\n", u32Format)); 389 EmptyClipboard();205 VBoxClipboardWinClear(); 390 206 } 391 207 else … … 518 334 519 335 /* Something went wrong. */ 520 EmptyClipboard();336 VBoxClipboardWinClear(); 521 337 } 522 338 } break; … … 527 343 * windows is to be destroyed and therefore the guest side becomes inactive. 528 344 */ 529 int vboxrc = vboxOpenClipboard(hwnd);345 int vboxrc = VBoxClipboardWinOpen(hwnd); 530 346 if (RT_SUCCESS(vboxrc)) 531 347 { 532 EmptyClipboard();533 CloseClipboard();534 } 535 } break; 536 537 case VBOX_ WM_SHCLPB_SET_FORMATS:348 VBoxClipboardWinClear(); 349 VBoxClipboardWinClose(); 350 } 351 } break; 352 353 case VBOX_CLIPBOARD_WM_SET_FORMATS: 538 354 { 539 355 /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */ … … 542 358 LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: u32Formats=0x%x\n", u32Formats)); 543 359 544 int vboxrc = vboxOpenClipboard(hwnd);360 int vboxrc = VBoxClipboardWinOpen(hwnd); 545 361 if (RT_SUCCESS(vboxrc)) 546 362 { 547 EmptyClipboard();363 VBoxClipboardWinClear(); 548 364 549 365 HANDLE hClip = NULL; … … 562 378 } 563 379 564 CloseClipboard();380 VBoxClipboardWinClose(); 565 381 566 382 LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError())); … … 568 384 } break; 569 385 570 case VBOX_ WM_SHCLPB_READ_DATA:386 case VBOX_CLIPBOARD_WM_READ_DATA: 571 387 { 572 388 /* Send data in the specified format to the host. */ … … 576 392 LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats)); 577 393 578 int vboxrc = vboxOpenClipboard(hwnd);394 int vboxrc = VBoxClipboardWinOpen(hwnd); 579 395 if (RT_SUCCESS(vboxrc)) 580 396 { … … 642 458 } 643 459 644 CloseClipboard();460 VBoxClipboardWinClose(); 645 461 } 646 462 … … 654 470 case WM_DESTROY: 655 471 { 656 vboxClipboardRemoveFromCBChain(pCtx);657 if (p Ctx->timerRefresh)658 KillTimer(p Ctx->hwnd, 0);472 VBoxClipboardWinRemoveFromCBChain(pWinCtx); 473 if (pWinCtx->oldAPI.timerRefresh) 474 KillTimer(pWinCtx->hWnd, 0); 659 475 /* 660 476 * don't need to call PostQuitMessage cause … … 699 515 wc.lpszClassName = s_szClipWndClassName; 700 516 701 pCtx->wndClass = RegisterClassEx(&wc);702 if ( pCtx->wndClass == 0)517 ATOM wndClass = RegisterClassEx(&wc); 518 if (wndClass == 0) 703 519 rc = RTErrConvertFromWin32(GetLastError()); 704 520 } … … 706 522 if (RT_SUCCESS(rc)) 707 523 { 524 const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win; 525 708 526 /* Create the window. */ 709 p Ctx->hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,710 s_szClipWndClassName, s_szClipWndClassName,711 WS_POPUPWINDOW,712 -200, -200, 100, 100, NULL, NULL, hInstance, NULL);713 if (p Ctx->hwnd == NULL)527 pWinCtx->hWnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST, 528 s_szClipWndClassName, s_szClipWndClassName, 529 WS_POPUPWINDOW, 530 -200, -200, 100, 100, NULL, NULL, hInstance, NULL); 531 if (pWinCtx->hWnd == NULL) 714 532 { 715 533 rc = VERR_NOT_SUPPORTED; … … 717 535 else 718 536 { 719 SetWindowPos(p Ctx->hwnd, HWND_TOPMOST, -200, -200, 0, 0,537 SetWindowPos(pWinCtx->hWnd, HWND_TOPMOST, -200, -200, 0, 0, 720 538 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE); 721 539 722 vboxClipboardAddToCBChain(pCtx);723 if (! vboxClipboardIsNewAPI(pCtx))724 p Ctx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);540 VBoxClipboardWinAddToCBChain(pWinCtx); 541 if (!VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI)) 542 pWinCtx->oldAPI.timerRefresh = SetTimer(pWinCtx->hWnd, 0, 10 * 1000 /* 10s */, NULL); 725 543 } 726 544 } … … 734 552 AssertPtrReturnVoid(pCtx); 735 553 736 if (pCtx->hwnd) 554 const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win; 555 556 if (pWinCtx->hWnd) 737 557 { 738 DestroyWindow(p Ctx->hwnd);739 p Ctx->hwnd = NULL;558 DestroyWindow(pWinCtx->hWnd); 559 pWinCtx->hWnd = NULL; 740 560 } 741 561 742 if (pCtx->wndClass != 0) 743 { 744 UnregisterClass(s_szClipWndClassName, pCtx->pEnv->hInstance); 745 pCtx->wndClass = 0; 746 } 562 UnregisterClass(s_szClipWndClassName, pCtx->pEnv->hInstance); 747 563 } 748 564 … … 777 593 778 594 RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT)); 595 779 596 pCtx->pEnv = pEnv; 780 597 781 598 /* Check that new Clipboard API is available */ 782 vboxClipboardInitNewAPI(pCtx);599 VBoxClipboardWinCheckAndInitNewAPI(&pCtx->Win.newAPI); 783 600 784 601 int rc = VbglR3ClipboardConnect(&pCtx->u32ClientID); … … 811 628 RTThreadUserSignal(RTThreadSelf()); 812 629 813 PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)pInstance;630 const PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)pInstance; 814 631 AssertPtr(pCtx); 632 633 const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win; 815 634 816 635 int rc; … … 846 665 * Forward the information to the window, so it can later 847 666 * respond to WM_RENDERFORMAT message. */ 848 ::PostMessage(p Ctx->hwnd, VBOX_WM_SHCLPB_SET_FORMATS, 0, u32Formats);667 ::PostMessage(pWinCtx->hWnd, VBOX_CLIPBOARD_WM_SET_FORMATS, 0, u32Formats); 849 668 } break; 850 669 … … 852 671 { 853 672 /* The host needs data in the specified format. */ 854 ::PostMessage(p Ctx->hwnd, VBOX_WM_SHCLPB_READ_DATA, 0, u32Formats);673 ::PostMessage(pWinCtx->hWnd, VBOX_CLIPBOARD_WM_READ_DATA, 0, u32Formats); 855 674 } break; 856 675 … … 927 746 VBoxClipboardDestroy 928 747 }; 748 -
trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk
r76970 r78151 35 35 VBoxSharedClipboard_SOURCES.win = \ 36 36 VBoxClipboard-win.cpp \ 37 $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp \ 37 38 VBoxSharedClipboardSvc.rc 38 39 VBoxSharedClipboard_SOURCES.darwin = \ -
trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp
r76553 r78151 24 24 25 25 #include <VBox/HostServices/VBoxClipboardSvc.h> 26 #include <VBox/GuestHost/SharedClipboard-win.h> 26 27 27 28 #include <iprt/alloc.h> … … 35 36 #include "VBoxClipboard.h" 36 37 37 #define dprintf Log 38 39 static char gachWindowClassName[] = "VBoxSharedClipboardClass"; 40 41 enum { CBCHAIN_TIMEOUT = 5000 /* ms */ }; 42 43 /* Dynamically load clipboard functions from User32.dll. */ 44 typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND); 45 typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER; 46 47 typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND); 48 typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER; 49 38 /** Static window class name. */ 39 static char s_szClipWndClassName[] = VBOX_CLIPBOARD_WNDCLASS_NAME; 50 40 51 41 /********************************************************************************************************************************* … … 55 45 static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput); 56 46 static bool IsWindowsHTML(const char *source); 57 58 59 #ifndef WM_CLIPBOARDUPDATE 60 #define WM_CLIPBOARDUPDATE 0x031D 61 #endif 47 static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx); 62 48 63 49 struct _VBOXCLIPBOARDCONTEXT 64 50 { 65 HWND hwnd; 66 HWND hwndNextInChain; 67 68 UINT timerRefresh; 69 70 bool fCBChainPingInProcess; 71 72 RTTHREAD thread; 73 74 HANDLE hRenderEvent; 75 76 VBOXCLIPBOARDCLIENTDATA *pClient; 77 78 PFNADDCLIPBOARDFORMATLISTENER pfnAddClipboardFormatListener; 79 PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener; 80 51 /** Handle for window message handling thread. */ 52 RTTHREAD hThread; 53 /** Event which gets triggered if the host clipboard needs to render its data. */ 54 HANDLE hRenderEvent; 55 /** Structure for keeping and communicating with client data (from the guest). */ 56 PVBOXCLIPBOARDCLIENTDATA pClient; 57 /** Windows-specific context data. */ 58 VBOXCLIPBOARDWINCTX Win; 81 59 }; 82 60 … … 86 64 87 65 #ifdef LOG_ENABLED 88 void vboxClipboardDump(const void *pv, size_t cb, uint32_t u32Format)66 static void vboxClipboardDump(const void *pv, size_t cb, uint32_t u32Format) 89 67 { 90 68 if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 91 69 { 92 Log (("DUMP:VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT:\n"));70 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT:\n")); 93 71 if (pv && cb) 94 Log (("%ls\n", pv));72 LogFunc(("%ls\n", pv)); 95 73 else 96 Log (("%p %d\n", pv, cb));74 LogFunc(("%p %zu\n", pv, cb)); 97 75 } 98 76 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 99 dprintf(("DUMP:VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));77 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n")); 100 78 else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML) 101 79 { 102 Log (("DUMP:VBOX_SHARED_CLIPBOARD_FMT_HTML:\n"));80 LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_HTML:\n")); 103 81 if (pv && cb) 104 82 { 105 Log (("%s\n", pv));83 LogFunc(("%s\n", pv)); 106 84 107 85 //size_t cb = RTStrNLen(pv, ); … … 114 92 } 115 93 116 Log (("%s\n", pszBuf));94 LogFunc(("%s\n", pszBuf)); 117 95 RTMemFree(pszBuf); 118 96 } 119 97 else 120 Log (("%p %d\n", pv, cb));98 LogFunc(("%p %zu\n", pv, cb)); 121 99 } 122 100 else 123 dprintf(("DUMP: invalid format %02X\n", u32Format));101 LogFunc(("Invalid format %02X\n", u32Format)); 124 102 } 125 103 #else /* !LOG_ENABLED */ … … 127 105 #endif /* !LOG_ENABLED */ 128 106 129 130 static void vboxClipboardInitNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)131 {132 RTLDRMOD hUser32 = NIL_RTLDRMOD;133 int rc = RTLdrLoadSystem("User32.dll", /* fNoUnload = */ true, &hUser32);134 if (RT_SUCCESS(rc))135 {136 rc = RTLdrGetSymbol(hUser32, "AddClipboardFormatListener", (void**)&pCtx->pfnAddClipboardFormatListener);137 if (RT_SUCCESS(rc))138 {139 rc = RTLdrGetSymbol(hUser32, "RemoveClipboardFormatListener", (void**)&pCtx->pfnRemoveClipboardFormatListener);140 }141 142 RTLdrClose(hUser32);143 }144 145 if (RT_SUCCESS(rc))146 {147 Log(("New Clipboard API is enabled\n"));148 }149 else150 {151 pCtx->pfnAddClipboardFormatListener = NULL;152 pCtx->pfnRemoveClipboardFormatListener = NULL;153 Log(("New Clipboard API is not available. rc = %Rrc\n", rc));154 }155 }156 157 static bool vboxClipboardIsNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)158 {159 return pCtx->pfnAddClipboardFormatListener != NULL;160 }161 162 163 static int vboxOpenClipboard(HWND hwnd)164 {165 /* "OpenClipboard fails if another window has the clipboard open."166 * So try a few times and wait up to 1 second.167 */168 BOOL fOpened = FALSE;169 170 int i = 0;171 for (;;)172 {173 if (OpenClipboard(hwnd))174 {175 fOpened = TRUE;176 break;177 }178 179 if (i >= 10) /* sleep interval = [1..512] ms */180 break;181 182 RTThreadSleep(1 << i);183 ++i;184 }185 186 #ifdef LOG_ENABLED187 if (i > 0)188 LogFlowFunc(("%d times tried to open clipboard.\n", i + 1));189 #endif190 191 int rc;192 if (fOpened)193 rc = VINF_SUCCESS;194 else195 {196 const DWORD err = GetLastError();197 LogFlowFunc(("error %d\n", err));198 rc = RTErrConvertFromWin32(err);199 }200 201 return rc;202 }203 204 205 107 /** @todo Someone please explain the protocol wrt overflows... */ 206 108 static void vboxClipboardGetData (uint32_t u32Format, const void *pvSrc, uint32_t cbSrc, 207 109 void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst) 208 110 { 209 dprintf (("vboxClipboardGetData.\n"));210 211 111 LogFlow(("vboxClipboardGetData cbSrc = %d, cbDst = %d\n", cbSrc, cbDst)); 212 112 … … 270 170 } 271 171 272 static void vboxClipboardChanged (VBOXCLIPBOARDCONTEXT *pCtx)273 {274 LogFlow(("vboxClipboardChanged\n"));275 276 if (pCtx->pClient == NULL)277 {278 return;279 }280 281 /* Query list of available formats and report to host. */282 int rc = vboxOpenClipboard(pCtx->hwnd);283 if (RT_SUCCESS(rc))284 {285 uint32_t u32Formats = 0;286 287 UINT format = 0;288 289 while ((format = EnumClipboardFormats (format)) != 0)290 {291 LogFlow(("vboxClipboardChanged format %#x\n", format));292 switch (format)293 {294 case CF_UNICODETEXT:295 case CF_TEXT:296 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;297 break;298 299 case CF_DIB:300 case CF_BITMAP:301 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;302 break;303 304 default:305 if (format >= 0xC000)306 {307 TCHAR szFormatName[256];308 309 int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));310 311 if (cActual)312 {313 if (strcmp (szFormatName, "HTML Format") == 0)314 {315 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_HTML;316 }317 }318 }319 break;320 }321 }322 323 CloseClipboard ();324 325 LogFlow(("vboxClipboardChanged u32Formats %02X\n", u32Formats));326 327 vboxSvcClipboardReportMsg (pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, u32Formats);328 }329 else330 {331 LogFlow(("vboxClipboardChanged: error in open clipboard. hwnd: %x. err: %Rrc\n", pCtx->hwnd, rc));332 }333 }334 335 /* Add ourselves into the chain of cliboard listeners */336 static void addToCBChain (VBOXCLIPBOARDCONTEXT *pCtx)337 {338 if (vboxClipboardIsNewAPI(pCtx))339 pCtx->pfnAddClipboardFormatListener(pCtx->hwnd);340 else341 pCtx->hwndNextInChain = SetClipboardViewer(pCtx->hwnd);342 }343 344 /* Remove ourselves from the chain of cliboard listeners */345 static void removeFromCBChain (VBOXCLIPBOARDCONTEXT *pCtx)346 {347 if (vboxClipboardIsNewAPI(pCtx))348 {349 pCtx->pfnRemoveClipboardFormatListener(pCtx->hwnd);350 }351 else352 {353 ChangeClipboardChain(pCtx->hwnd, pCtx->hwndNextInChain);354 pCtx->hwndNextInChain = NULL;355 }356 }357 358 /* Callback which is invoked when we have successfully pinged ourselves down the359 * clipboard chain. We simply unset a boolean flag to say that we are responding.360 * There is a race if a ping returns after the next one is initiated, but nothing361 * very bad is likely to happen. */362 VOID CALLBACK CBChainPingProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)363 {364 (void) hwnd;365 (void) uMsg;366 (void) lResult;367 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)dwData;368 pCtx->fCBChainPingInProcess = FALSE;369 }370 371 172 static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 372 173 { 373 174 LRESULT rc = 0; 374 175 375 VBOXCLIPBOARDCONTEXT *pCtx = &g_ctx;176 PVBOXCLIPBOARDCONTEXT pCtx = &g_ctx; 376 177 377 178 switch (msg) … … 383 184 if (GetClipboardOwner() != hwnd) 384 185 { 385 /* Clipboard was updated by another application. */ 386 vboxClipboardChanged(pCtx); 186 /* Clipboard was updated by another application, retrieve formats and report back. */ 187 int vboxrc = vboxClipboardSyncInternal(pCtx); 188 AssertRC(vboxrc); 387 189 } 388 190 } break; … … 392 194 Log(("WM_CHANGECBCHAIN\n")); 393 195 394 if ( vboxClipboardIsNewAPI(pCtx))196 if (VBoxClipboardWinIsNewAPI(&pCtx->Win.newAPI)) 395 197 { 396 198 rc = DefWindowProc(hwnd, msg, wParam, lParam); … … 401 203 HWND hwndNext = (HWND)lParam; 402 204 403 if (hwndRemoved == pCtx-> hwndNextInChain)205 if (hwndRemoved == pCtx->Win.hWndNextInChain) 404 206 { 405 207 /* The window that was next to our in the chain is being removed. 406 208 * Relink to the new next window. 407 209 */ 408 pCtx-> hwndNextInChain = hwndNext;210 pCtx->Win.hWndNextInChain = hwndNext; 409 211 } 410 212 else 411 213 { 412 if (pCtx-> hwndNextInChain)214 if (pCtx->Win.hWndNextInChain) 413 215 { 414 216 /* Pass the message further. */ 415 217 DWORD_PTR dwResult; 416 rc = SendMessageTimeout(pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult); 218 rc = SendMessageTimeout(pCtx->Win.hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, 219 VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, 220 &dwResult); 417 221 if (!rc) 418 222 rc = (LRESULT)dwResult; … … 425 229 Log(("WM_DRAWCLIPBOARD\n")); 426 230 427 if (GetClipboardOwner () != hwnd) 428 { 429 /* Clipboard was updated by another application. */ 430 vboxClipboardChanged (pCtx); 431 } 432 433 if (pCtx->hwndNextInChain) 434 { 435 Log(("WM_DRAWCLIPBOARD next %p\n", pCtx->hwndNextInChain)); 231 if (GetClipboardOwner() != hwnd) 232 { 233 /* Clipboard was updated by another application, retrieve formats and report back. */ 234 int vboxrc = vboxClipboardSyncInternal(pCtx); 235 AssertRC(vboxrc); 236 } 237 238 if (pCtx->Win.hWndNextInChain) 239 { 240 Log(("WM_DRAWCLIPBOARD next %p\n", pCtx->Win.hWndNextInChain)); 436 241 /* Pass the message to next windows in the clipboard chain. */ 437 242 DWORD_PTR dwResult; 438 rc = SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult); 243 rc = SendMessageTimeout(pCtx->Win.hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, 244 &dwResult); 439 245 if (!rc) 440 246 rc = dwResult; … … 444 250 case WM_TIMER: 445 251 { 446 if ( vboxClipboardIsNewAPI(pCtx))252 if (VBoxClipboardWinIsNewAPI(&pCtx->Win.newAPI)) 447 253 break; 448 254 … … 451 257 /* Re-register ourselves in the clipboard chain if our last ping 452 258 * timed out or there seems to be no valid chain. */ 453 if (!hViewer || pCtx->fCBChainPingInProcess) 454 { 455 removeFromCBChain(pCtx); 456 addToCBChain(pCtx); 457 } 259 if (!hViewer || pCtx->Win.oldAPI.fCBChainPingInProcess) 260 { 261 VBoxClipboardWinRemoveFromCBChain(&pCtx->Win); 262 VBoxClipboardWinAddToCBChain(&pCtx->Win); 263 } 264 458 265 /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be 459 266 * processed by ourselves to the chain. */ 460 pCtx->fCBChainPingInProcess = TRUE; 267 pCtx->Win.oldAPI.fCBChainPingInProcess = TRUE; 268 461 269 hViewer = GetClipboardViewer(); 462 270 if (hViewer) 463 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, CBChainPingProc, (ULONG_PTR) pCtx); 271 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, 272 (WPARAM)pCtx->Win.hWndNextInChain, (LPARAM)pCtx->Win.hWndNextInChain, 273 VBoxClipboardWinChainPingProc, (ULONG_PTR)pCtx); 464 274 } break; 465 275 … … 511 321 int vboxrc = vboxClipboardReadDataFromClient (pCtx, u32Format); 512 322 513 dprintf(("vboxClipboardReadDataFromClient vboxrc = %d, pv %p, cb %d, u32Format %d\n",323 LogFunc(("vboxClipboardReadDataFromClient vboxrc = %d, pv %p, cb %d, u32Format %d\n", 514 324 vboxrc, pCtx->pClient->data.pv, pCtx->pClient->data.cb, pCtx->pClient->data.u32Format)); 515 325 … … 521 331 HANDLE hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, pCtx->pClient->data.cb); 522 332 523 dprintf(("hMem %p\n", hMem));333 LogFunc(("hMem %p\n", hMem)); 524 334 525 335 if (hMem) … … 527 337 void *pMem = GlobalLock (hMem); 528 338 529 dprintf(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));339 LogFunc(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem))); 530 340 531 341 if (pMem) … … 552 362 HANDLE hClip = SetClipboardData (format, hMem); 553 363 554 dprintf(("vboxClipboardHostEvent hClip %p\n", hClip));364 LogFunc(("vboxClipboardHostEvent hClip %p\n", hClip)); 555 365 556 366 if (hClip) … … 571 381 572 382 /* Something went wrong. */ 573 EmptyClipboard();383 VBoxClipboardWinClear(); 574 384 } 575 385 } break; … … 582 392 * windows is to be destroyed and therefore the guest side becomes inactive. 583 393 */ 584 int vboxrc = vboxOpenClipboard(hwnd);394 int vboxrc = VBoxClipboardWinOpen(hwnd); 585 395 if (RT_SUCCESS(vboxrc)) 586 396 { 587 EmptyClipboard(); 588 589 CloseClipboard(); 397 VBoxClipboardWinClear(); 398 VBoxClipboardWinClose(); 590 399 } 591 400 else … … 595 404 } break; 596 405 597 case WM_USER:406 case VBOX_CLIPBOARD_WM_SET_FORMATS: 598 407 { 599 408 if (pCtx->pClient == NULL || pCtx->pClient->fMsgFormats) … … 602 411 * because host clipboard has more priority. 603 412 */ 604 Log((" WM_USERignored\n"));413 Log(("VBOX_CLIPBOARD_WM_SET_FORMATS ignored\n")); 605 414 break; 606 415 } … … 609 418 uint32_t u32Formats = (uint32_t)lParam; 610 419 611 Log((" WM_USER u32Formats =%02X\n", u32Formats));612 613 int vboxrc = vboxOpenClipboard(hwnd);420 Log(("VBOX_CLIPBOARD_WM_SET_FORMATS: u32Formats=%02X\n", u32Formats)); 421 422 int vboxrc = VBoxClipboardWinOpen(hwnd); 614 423 if (RT_SUCCESS(vboxrc)) 615 424 { 616 EmptyClipboard();617 618 Log((" WM_USERemptied clipboard\n"));425 VBoxClipboardWinClear(); 426 427 Log(("VBOX_CLIPBOARD_WM_SET_FORMATS emptied clipboard\n")); 619 428 620 429 HANDLE hClip = NULL; 621 430 622 431 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 623 { 624 dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n")); 625 626 hClip = SetClipboardData (CF_UNICODETEXT, NULL); 627 } 432 hClip = SetClipboardData(CF_UNICODETEXT, NULL); 628 433 629 434 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) 630 { 631 dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n")); 632 633 hClip = SetClipboardData (CF_DIB, NULL); 634 } 435 hClip = SetClipboardData(CF_DIB, NULL); 635 436 636 437 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML) 637 438 { 638 439 UINT format = RegisterClipboardFormat ("HTML Format"); 639 dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_HTML 0x%04X\n", format));640 440 if (format != 0) 641 441 { … … 644 444 } 645 445 646 CloseClipboard(); 647 648 dprintf(("window proc WM_USER: hClip %p, err %d\n", hClip, GetLastError ())); 649 } 650 else 651 { 652 dprintf(("window proc WM_USER: failed to open clipboard. rc: %Rrc\n", vboxrc)); 446 VBoxClipboardWinClose(); 447 448 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError ())); 653 449 } 654 450 } break; … … 656 452 case WM_DESTROY: 657 453 { 658 /* MS recommends to remove from Clipboard chain in this callback */ 659 Assert(pCtx->hwnd); 660 removeFromCBChain(pCtx); 661 if (pCtx->timerRefresh) 662 KillTimer(pCtx->hwnd, 0); 454 /* MS recommends to remove from Clipboard chain in this callback. */ 455 VBoxClipboardWinRemoveFromCBChain(&pCtx->Win); 456 if (pCtx->Win.oldAPI.timerRefresh) 457 { 458 Assert(pCtx->Win.hWnd); 459 KillTimer(pCtx->Win.hWnd, 0); 460 } 663 461 PostQuitMessage(0); 664 462 } break; … … 683 481 LogFlow(("VBoxClipboardThread\n")); 684 482 685 VBOXCLIPBOARDCONTEXT *pCtx = &g_ctx;483 const PVBOXCLIPBOARDCONTEXT pCtx = &g_ctx; 686 484 687 485 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); … … 695 493 wc.hInstance = hInstance; 696 494 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1); 697 wc.lpszClassName = gachWindowClassName;495 wc.lpszClassName = s_szClipWndClassName; 698 496 699 497 ATOM atomWindowClass = RegisterClass(&wc); … … 707 505 { 708 506 /* Create the window. */ 709 pCtx->hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST, 710 gachWindowClassName, gachWindowClassName, 711 WS_POPUPWINDOW, 712 -200, -200, 100, 100, NULL, NULL, hInstance, NULL); 713 714 if (pCtx->hwnd == NULL) 507 pCtx->Win.hWnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST, 508 s_szClipWndClassName, s_szClipWndClassName, 509 WS_POPUPWINDOW, 510 -200, -200, 100, 100, NULL, NULL, hInstance, NULL); 511 if (pCtx->Win.hWnd == NULL) 715 512 { 716 513 Log(("Failed to create window\n")); … … 719 516 else 720 517 { 721 SetWindowPos(pCtx-> hwnd, HWND_TOPMOST, -200, -200, 0, 0,518 SetWindowPos(pCtx->Win.hWnd, HWND_TOPMOST, -200, -200, 0, 0, 722 519 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE); 723 520 724 addToCBChain(pCtx);725 if (! vboxClipboardIsNewAPI(pCtx))726 pCtx-> timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);521 VBoxClipboardWinAddToCBChain(&pCtx->Win); 522 if (!VBoxClipboardWinIsNewAPI(&pCtx->Win.newAPI)) 523 pCtx->Win.oldAPI.timerRefresh = SetTimer(pCtx->Win.hWnd, 0, 10 * 1000, NULL); 727 524 728 525 MSG msg; … … 743 540 } 744 541 745 pCtx-> hwnd = NULL;542 pCtx->Win.hWnd = NULL; 746 543 747 544 if (atomWindowClass != 0) 748 545 { 749 UnregisterClass ( gachWindowClassName, hInstance);546 UnregisterClass (s_szClipWndClassName, hInstance); 750 547 atomWindowClass = 0; 751 548 } 752 549 753 550 return 0; 551 } 552 553 /** 554 * Synchronizes the host and the guest clipboard formats by sending all supported host clipboard 555 * formats to the guest. 556 * 557 * @returns VBox status code. 558 * @param pCtx Clipboard context to synchronize. 559 */ 560 static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx) 561 { 562 uint32_t uFormats; 563 int rc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats); 564 if (RT_SUCCESS(rc)) 565 vboxSvcClipboardReportMsg(pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, uFormats); 566 567 return rc; 754 568 } 755 569 … … 763 577 RT_ZERO(g_ctx); 764 578 765 /* Check that new Clipboard API is available */766 vboxClipboardInitNewAPI(&g_ctx);579 /* Check that new Clipboard API is available. */ 580 VBoxClipboardWinCheckAndInitNewAPI(&g_ctx.Win.newAPI); 767 581 768 582 g_ctx.hRenderEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 769 583 770 rc = RTThreadCreate (&g_ctx. thread, VBoxClipboardThread, NULL, 65536,584 rc = RTThreadCreate (&g_ctx.hThread, VBoxClipboardThread, NULL, 65536, 771 585 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP"); 772 586 … … 783 597 Log(("vboxClipboardDestroy\n")); 784 598 785 if (g_ctx. hwnd)786 { 787 PostMessage (g_ctx. hwnd, WM_CLOSE, 0, 0);599 if (g_ctx.Win.hWnd) 600 { 601 PostMessage (g_ctx.Win.hWnd, WM_CLOSE, 0, 0); 788 602 } 789 603 … … 791 605 792 606 /* Wait for the window thread to terminate. */ 793 RTThreadWait (g_ctx. thread, RT_INDEFINITE_WAIT, NULL);794 795 g_ctx. thread = NIL_RTTHREAD;607 RTThreadWait (g_ctx.hThread, RT_INDEFINITE_WAIT, NULL); 608 609 g_ctx.hThread = NIL_RTTHREAD; 796 610 } 797 611 … … 820 634 { 821 635 /* Sync the host clipboard content with the client. */ 822 vboxClipboardChanged (pClient->pCtx); 823 824 return VINF_SUCCESS; 636 return vboxClipboardSyncInternal(pClient->pCtx); 825 637 } 826 638 … … 838 650 * The guest announces formats. Forward to the window thread. 839 651 */ 840 PostMessage (pClient->pCtx-> hwnd, WM_USER, 0, u32Formats);652 PostMessage (pClient->pCtx->Win.hWnd, WM_USER, 0, u32Formats); 841 653 } 842 654 … … 880 692 * The guest wants to read data in the given format. 881 693 */ 882 int rc = vboxOpenClipboard(pClient->pCtx->hwnd);694 int rc = VBoxClipboardWinOpen(pClient->pCtx->Win.hWnd); 883 695 if (RT_SUCCESS(rc)) 884 696 { 885 dprintf(("Clipboard opened.\n"));697 LogFunc(("Clipboard opened.\n")); 886 698 887 699 if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_BITMAP) … … 895 707 if (lp != NULL) 896 708 { 897 dprintf(("CF_DIB\n"));709 LogFunc(("CF_DIB\n")); 898 710 899 711 vboxClipboardGetData (VBOX_SHARED_CLIPBOARD_FMT_BITMAP, lp, GlobalSize (hClip), … … 918 730 if (uniString != NULL) 919 731 { 920 dprintf(("CF_UNICODETEXT\n"));732 LogFunc(("CF_UNICODETEXT\n")); 921 733 922 734 vboxClipboardGetData (VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, uniString, (lstrlenW (uniString) + 1) * 2, … … 945 757 if (lp != NULL) 946 758 { 947 dprintf(("CF_HTML\n"));759 LogFunc(("CF_HTML\n")); 948 760 949 761 vboxClipboardGetData (VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize (hClip), … … 961 773 } 962 774 963 CloseClipboard();775 VBoxClipboardWinClose(); 964 776 } 965 777 else 966 778 { 967 dprintf(("vboxClipboardReadData: failed to open clipboard, rc: %Rrc\n", rc));779 LogFunc(("vboxClipboardReadData: failed to open clipboard, rc: %Rrc\n", rc)); 968 780 } 969 781 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h
r76570 r78151 25 25 #include <VBox/log.h> 26 26 27 struct _VBOXCLIPBOARDCONTEXT; 28 typedef struct _VBOXCLIPBOARDCONTEXT VBOXCLIPBOARDCONTEXT; 29 27 #include <VBox/GuestHost/SharedClipboard.h> 30 28 31 29 typedef struct _VBOXCLIPBOARDCLIENTDATA … … 64 62 uint32_t u32RequestedFormat; 65 63 66 } VBOXCLIPBOARDCLIENTDATA ;64 } VBOXCLIPBOARDCLIENTDATA, *PVBOXCLIPBOARDCLIENTDATA; 67 65 68 66 /* 69 67 * The service functions. Locking is between the service thread and the platform dependent windows thread. 70 68 */ 71 bool vboxSvcClipboardLock (void);72 void vboxSvcClipboardUnlock (void);73 74 69 void vboxSvcClipboardReportMsg (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats); 75 76 70 void vboxSvcClipboardCompleteReadData(VBOXCLIPBOARDCLIENTDATA *pClient, int rc, uint32_t cbActual); 77 78 bool vboxSvcClipboardGetHeadless(void);79 71 80 72 /* … … 86 78 int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless); 87 79 void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient); 88 89 80 void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats); 90 91 81 int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual); 92 93 82 void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format); 94 83 -
trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
r76970 r78151 109 109 static bool g_fHeadless = false; 110 110 111 static bool vboxSvcClipboardGetHeadless(void); 112 static bool vboxSvcClipboardLock(void); 113 static void vboxSvcClipboardUnlock(void); 114 111 115 112 116 static void VBoxHGCMParmUInt32Set (VBOXHGCMSVCPARM *pParm, uint32_t u32) … … 163 167 164 168 /** Getter for headless setting */ 165 bool vboxSvcClipboardGetHeadless(void)169 static bool vboxSvcClipboardGetHeadless(void) 166 170 { 167 171 return g_fHeadless; … … 184 188 } 185 189 186 bool vboxSvcClipboardLock (void)190 static bool vboxSvcClipboardLock (void) 187 191 { 188 192 return RT_SUCCESS(RTCritSectEnter (&critsect)); 189 193 } 190 194 191 void vboxSvcClipboardUnlock(void)195 static void vboxSvcClipboardUnlock(void) 192 196 { 193 197 RTCritSectLeave (&critsect);
Note:
See TracChangeset
for help on using the changeset viewer.

