VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp@ 53517

Last change on this file since 53517 was 51469, checked in by vboxsync, 11 years ago

VBoxTray: Logging; ripped out all custom logging.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.7 KB
Line 
1/** @file
2 *
3 * VBoxClipboard - Shared clipboard
4 *
5 */
6
7/*
8 * Copyright (C) 2006-2014 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "VBoxTray.h"
20#include "VBoxHelpers.h"
21
22#include <VBox/HostServices/VBoxClipboardSvc.h>
23#include <strsafe.h>
24
25#include <VBox/VMMDev.h>
26#ifdef DEBUG
27# define LOG_ENABLED
28# define LOG_GROUP LOG_GROUP_DEFAULT
29#endif
30#include <VBox/log.h>
31
32
33
34typedef struct _VBOXCLIPBOARDCONTEXT
35{
36 const VBOXSERVICEENV *pEnv;
37
38 uint32_t u32ClientID;
39
40 ATOM atomWindowClass;
41
42 HWND hwnd;
43
44 HWND hwndNextInChain;
45
46 UINT timerRefresh;
47
48 bool fCBChainPingInProcess;
49
50// bool fOperational;
51
52// uint32_t u32LastSentFormat;
53// uint64_t u64LastSentCRC64;
54
55} VBOXCLIPBOARDCONTEXT;
56
57static char gachWindowClassName[] = "VBoxSharedClipboardClass";
58
59enum { CBCHAIN_TIMEOUT = 5000 /* ms */ };
60
61static int vboxClipboardChanged(VBOXCLIPBOARDCONTEXT *pCtx)
62{
63 AssertPtr(pCtx);
64
65 /* Query list of available formats and report to host. */
66 int rc = VINF_SUCCESS;
67 if (FALSE == OpenClipboard(pCtx->hwnd))
68 {
69 rc = RTErrConvertFromWin32(GetLastError());
70 }
71 else
72 {
73 uint32_t u32Formats = 0;
74 UINT format = 0;
75
76 while ((format = EnumClipboardFormats (format)) != 0)
77 {
78 LogFlowFunc(("vboxClipboardChanged: format = 0x%08X\n", format));
79 switch (format)
80 {
81 case CF_UNICODETEXT:
82 case CF_TEXT:
83 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
84 break;
85
86 case CF_DIB:
87 case CF_BITMAP:
88 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
89 break;
90
91 default:
92 if (format >= 0xC000)
93 {
94 TCHAR szFormatName[256];
95
96 int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
97 if (cActual)
98 {
99 if (strcmp (szFormatName, "HTML Format") == 0)
100 {
101 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
102 }
103 }
104 }
105 break;
106 }
107 }
108
109 CloseClipboard ();
110 rc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, u32Formats);
111 }
112 return rc;
113}
114
115/* Add ourselves into the chain of cliboard listeners */
116static void addToCBChain (VBOXCLIPBOARDCONTEXT *pCtx)
117{
118 pCtx->hwndNextInChain = SetClipboardViewer (pCtx->hwnd);
119}
120
121/* Remove ourselves from the chain of cliboard listeners */
122static void removeFromCBChain (VBOXCLIPBOARDCONTEXT *pCtx)
123{
124 ChangeClipboardChain (pCtx->hwnd, pCtx->hwndNextInChain);
125 pCtx->hwndNextInChain = NULL;
126}
127
128/* Callback which is invoked when we have successfully pinged ourselves down the
129 * clipboard chain. We simply unset a boolean flag to say that we are responding.
130 * There is a race if a ping returns after the next one is initiated, but nothing
131 * very bad is likely to happen. */
132VOID CALLBACK CBChainPingProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)
133{
134 (void) hwnd;
135 (void) uMsg;
136 (void) lResult;
137 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)dwData;
138 pCtx->fCBChainPingInProcess = FALSE;
139}
140
141static LRESULT vboxClipboardProcessMsg(VBOXCLIPBOARDCONTEXT *pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
142{
143 LRESULT rc = 0;
144
145 switch (msg)
146 {
147 case WM_CHANGECBCHAIN:
148 {
149 HWND hwndRemoved = (HWND)wParam;
150 HWND hwndNext = (HWND)lParam;
151
152 LogFlowFunc(("WM_CHANGECBCHAIN: hwndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));
153
154 if (hwndRemoved == pCtx->hwndNextInChain)
155 {
156 /* The window that was next to our in the chain is being removed.
157 * Relink to the new next window. */
158 pCtx->hwndNextInChain = hwndNext;
159 }
160 else
161 {
162 if (pCtx->hwndNextInChain)
163 {
164 /* Pass the message further. */
165 DWORD_PTR dwResult;
166 rc = SendMessageTimeout(pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult);
167 if (!rc)
168 rc = (LRESULT) dwResult;
169 }
170 }
171 } break;
172
173 case WM_DRAWCLIPBOARD:
174 {
175 LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));
176
177 if (GetClipboardOwner () != hwnd)
178 {
179 /* Clipboard was updated by another application. */
180 /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
181 int vboxrc = vboxClipboardChanged(pCtx);
182 if (RT_FAILURE(vboxrc))
183 LogFlowFunc(("vboxClipboardChanged failed, rc = %Rrc\n", vboxrc));
184 }
185
186 /* Pass the message to next windows in the clipboard chain. */
187 SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, NULL);
188 } break;
189
190 case WM_TIMER:
191 {
192 HWND hViewer = GetClipboardViewer();
193
194 /* Re-register ourselves in the clipboard chain if our last ping
195 * timed out or there seems to be no valid chain. */
196 if (!hViewer || pCtx->fCBChainPingInProcess)
197 {
198 removeFromCBChain(pCtx);
199 addToCBChain(pCtx);
200 }
201 /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
202 * processed by ourselves to the chain. */
203 pCtx->fCBChainPingInProcess = TRUE;
204 hViewer = GetClipboardViewer();
205 if (hViewer)
206 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, CBChainPingProc, (ULONG_PTR) pCtx);
207 } break;
208
209 case WM_CLOSE:
210 {
211 /* Do nothing. Ignore the message. */
212 } break;
213
214 case WM_RENDERFORMAT:
215 {
216 /* Insert the requested clipboard format data into the clipboard. */
217 uint32_t u32Format = 0;
218 UINT format = (UINT)wParam;
219
220 LogFlowFunc(("WM_RENDERFORMAT, format = %x\n", format));
221 switch (format)
222 {
223 case CF_UNICODETEXT:
224 u32Format |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
225 break;
226
227 case CF_DIB:
228 u32Format |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
229 break;
230
231 default:
232 if (format >= 0xC000)
233 {
234 TCHAR szFormatName[256];
235
236 int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
237 if (cActual)
238 {
239 if (strcmp (szFormatName, "HTML Format") == 0)
240 {
241 u32Format |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
242 }
243 }
244 }
245 break;
246 }
247
248 if (u32Format == 0)
249 {
250 /* Unsupported clipboard format is requested. */
251 LogFlowFunc(("Unsupported clipboard format requested: %ld\n", u32Format));
252 EmptyClipboard();
253 }
254 else
255 {
256 const uint32_t cbPrealloc = 4096; /* @todo r=andy Make it dynamic for supporting larger text buffers! */
257 uint32_t cb = 0;
258
259 /* Preallocate a buffer, most of small text transfers will fit into it. */
260 HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
261 LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));
262
263 if (hMem)
264 {
265 void *pMem = GlobalLock(hMem);
266 LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
267
268 if (pMem)
269 {
270 /* Read the host data to the preallocated buffer. */
271 int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, u32Format, pMem, cbPrealloc, &cb);
272 LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n", vboxrc));
273
274 if (RT_SUCCESS(vboxrc))
275 {
276 if (cb == 0)
277 {
278 /* 0 bytes returned means the clipboard is empty.
279 * Deallocate the memory and set hMem to NULL to get to
280 * the clipboard empty code path. */
281 GlobalUnlock(hMem);
282 GlobalFree(hMem);
283 hMem = NULL;
284 }
285 else if (cb > cbPrealloc)
286 {
287 GlobalUnlock(hMem);
288
289 /* The preallocated buffer is too small, adjust the size. */
290 hMem = GlobalReAlloc(hMem, cb, 0);
291 LogFlowFunc(("Reallocated hMem = %p\n", hMem));
292
293 if (hMem)
294 {
295 pMem = GlobalLock(hMem);
296 LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
297
298 if (pMem)
299 {
300 /* Read the host data to the preallocated buffer. */
301 uint32_t cbNew = 0;
302 vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, u32Format, pMem, cb, &cbNew);
303 LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));
304
305 if (RT_SUCCESS (vboxrc) && cbNew <= cb)
306 {
307 cb = cbNew;
308 }
309 else
310 {
311 GlobalUnlock(hMem);
312 GlobalFree(hMem);
313 hMem = NULL;
314 }
315 }
316 else
317 {
318 GlobalFree(hMem);
319 hMem = NULL;
320 }
321 }
322 }
323
324 if (hMem)
325 {
326 /* pMem is the address of the data. cb is the size of returned data. */
327 /* Verify the size of returned text, the memory block for clipboard
328 * must have the exact string size.
329 */
330 if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
331 {
332 size_t cbActual = 0;
333 HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
334 if (FAILED (hrc))
335 {
336 /* Discard invalid data. */
337 GlobalUnlock(hMem);
338 GlobalFree(hMem);
339 hMem = NULL;
340 }
341 else
342 {
343 /* cbActual is the number of bytes, excluding those used
344 * for the terminating null character.
345 */
346 cb = (uint32_t)(cbActual + 2);
347 }
348 }
349 }
350
351 if (hMem)
352 {
353 GlobalUnlock(hMem);
354
355 hMem = GlobalReAlloc(hMem, cb, 0);
356 LogFlowFunc(("Reallocated hMem = %p\n", hMem));
357
358 if (hMem)
359 {
360 /* 'hMem' contains the host clipboard data.
361 * size is 'cb' and format is 'format'. */
362 HANDLE hClip = SetClipboardData(format, hMem);
363 LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));
364
365 if (hClip)
366 {
367 /* The hMem ownership has gone to the system. Finish the processing. */
368 break;
369 }
370
371 /* Cleanup follows. */
372 }
373 }
374 }
375 if (hMem)
376 GlobalUnlock(hMem);
377 }
378 if (hMem)
379 GlobalFree(hMem);
380 }
381
382 /* Something went wrong. */
383 EmptyClipboard();
384 }
385 } break;
386
387 case WM_RENDERALLFORMATS:
388 {
389 /* Do nothing. The clipboard formats will be unavailable now, because the
390 * windows is to be destroyed and therefore the guest side becomes inactive.
391 */
392 if (OpenClipboard(hwnd))
393 {
394 EmptyClipboard();
395 CloseClipboard();
396 }
397 } break;
398
399 case WM_USER:
400 {
401 /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
402 uint32_t u32Formats = (uint32_t)lParam;
403
404 if (FALSE == OpenClipboard(hwnd))
405 {
406 LogFlowFunc(("WM_USER: Failed to open clipboard! Last error = %ld\n", GetLastError()));
407 }
408 else
409 {
410 EmptyClipboard();
411
412 HANDLE hClip = NULL;
413
414 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
415 {
416 LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
417 hClip = SetClipboardData(CF_UNICODETEXT, NULL);
418 }
419
420 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
421 {
422 LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
423 hClip = SetClipboardData(CF_DIB, NULL);
424 }
425
426 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
427 {
428 UINT format = RegisterClipboardFormat ("HTML Format");
429 LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_HTML 0x%04X\n", format));
430 if (format != 0)
431 {
432 hClip = SetClipboardData(format, NULL);
433 }
434 }
435
436 CloseClipboard();
437 LogFlowFunc(("WM_USER: hClip = %p, err = %ld\n", hClip, GetLastError ()));
438 }
439 } break;
440
441 case WM_USER + 1:
442 {
443 /* Send data in the specified format to the host. */
444 uint32_t u32Formats = (uint32_t)lParam;
445 HANDLE hClip = NULL;
446
447 if (FALSE == OpenClipboard(hwnd))
448 {
449 LogFlowFunc(("WM_USER: Failed to open clipboard! Last error = %ld\n", GetLastError()));
450 }
451 else
452 {
453 int vboxrc;
454 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
455 {
456 hClip = GetClipboardData(CF_DIB);
457
458 if (hClip != NULL)
459 {
460 LPVOID lp = GlobalLock(hClip);
461 if (lp != NULL)
462 {
463 LogFlowFunc(("WM_USER + 1: CF_DIB\n"));
464 vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
465 lp, GlobalSize(hClip));
466 GlobalUnlock(hClip);
467 }
468 else
469 {
470 hClip = NULL;
471 }
472 }
473 }
474 else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
475 {
476 hClip = GetClipboardData(CF_UNICODETEXT);
477
478 if (hClip != NULL)
479 {
480 LPWSTR uniString = (LPWSTR)GlobalLock(hClip);
481
482 if (uniString != NULL)
483 {
484 LogFlowFunc(("WM_USER + 1: CF_UNICODETEXT\n"));
485 vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
486 uniString, (lstrlenW(uniString) + 1) * 2);
487 GlobalUnlock(hClip);
488 }
489 else
490 {
491 hClip = NULL;
492 }
493 }
494 }
495 else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
496 {
497 UINT format = RegisterClipboardFormat ("HTML Format");
498 if (format != 0)
499 {
500 hClip = GetClipboardData(format);
501 if (hClip != NULL)
502 {
503 LPVOID lp = GlobalLock(hClip);
504
505 if (lp != NULL)
506 {
507 LogFlowFunc(("WM_USER + 1: CF_HTML\n"));
508 vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
509 lp, GlobalSize(hClip));
510 GlobalUnlock(hClip);
511 }
512 else
513 {
514 hClip = NULL;
515 }
516 }
517 }
518 }
519
520 CloseClipboard();
521 }
522
523 if (hClip == NULL)
524 {
525 /* Requested clipboard format is not available, send empty data. */
526 VbglR3ClipboardWriteData(pCtx->u32ClientID, 0, NULL, 0);
527 }
528 } break;
529
530 default:
531 {
532 rc = DefWindowProc(hwnd, msg, wParam, lParam);
533 }
534 }
535
536#ifndef DEBUG_andy
537 LogFlowFunc(("vboxClipboardProcessMsg returned with rc = %ld\n", rc));
538#endif
539 return rc;
540}
541
542static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
543
544static int vboxClipboardInit (VBOXCLIPBOARDCONTEXT *pCtx)
545{
546 /* Register the Window Class. */
547 WNDCLASS wc;
548
549 wc.style = CS_NOCLOSE;
550 wc.lpfnWndProc = vboxClipboardWndProc;
551 wc.cbClsExtra = 0;
552 wc.cbWndExtra = 0;
553 wc.hInstance = pCtx->pEnv->hInstance;
554 wc.hIcon = NULL;
555 wc.hCursor = NULL;
556 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
557 wc.lpszMenuName = NULL;
558 wc.lpszClassName = gachWindowClassName;
559
560 pCtx->atomWindowClass = RegisterClass (&wc);
561
562 int rc = VINF_SUCCESS;
563 if (pCtx->atomWindowClass == 0)
564 {
565 rc = VERR_NOT_SUPPORTED;
566 }
567 else
568 {
569 /* Create the window. */
570 pCtx->hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
571 gachWindowClassName, gachWindowClassName,
572 WS_POPUPWINDOW,
573 -200, -200, 100, 100, NULL, NULL, pCtx->pEnv->hInstance, NULL);
574
575 if (pCtx->hwnd == NULL)
576 {
577 rc = VERR_NOT_SUPPORTED;
578 }
579 else
580 {
581 SetWindowPos(pCtx->hwnd, HWND_TOPMOST, -200, -200, 0, 0,
582 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
583
584 addToCBChain(pCtx);
585 pCtx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);
586 }
587 }
588
589 LogFlowFunc(("vboxClipboardInit returned with rc = %Rrc\n", rc));
590 return rc;
591}
592
593static void vboxClipboardDestroy(VBOXCLIPBOARDCONTEXT *pCtx)
594{
595 if (pCtx->hwnd)
596 {
597 removeFromCBChain(pCtx);
598 if (pCtx->timerRefresh)
599 KillTimer(pCtx->hwnd, 0);
600
601 DestroyWindow (pCtx->hwnd);
602 pCtx->hwnd = NULL;
603 }
604
605 if (pCtx->atomWindowClass != 0)
606 {
607 UnregisterClass(gachWindowClassName, pCtx->pEnv->hInstance);
608 pCtx->atomWindowClass = 0;
609 }
610}
611
612/* Static since it is the single instance. Directly used in the windows proc. */
613static VBOXCLIPBOARDCONTEXT gCtx = { NULL };
614
615static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
616{
617 /* Forward with proper context. */
618 return vboxClipboardProcessMsg(&gCtx, hwnd, msg, wParam, lParam);
619}
620
621int VBoxClipboardInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
622{
623 LogFlowFunc(("VBoxClipboardInit\n"));
624 if (gCtx.pEnv)
625 {
626 /* Clipboard was already initialized. 2 or more instances are not supported. */
627 return VERR_NOT_SUPPORTED;
628 }
629
630 if (VbglR3AutoLogonIsRemoteSession())
631 {
632 /* Do not use clipboard for remote sessions. */
633 LogRel(("VBoxTray: clipboard has been disabled for a remote session.\n"));
634 return VERR_NOT_SUPPORTED;
635 }
636
637 RT_ZERO (gCtx);
638 gCtx.pEnv = pEnv;
639
640 int rc = VbglR3ClipboardConnect(&gCtx.u32ClientID);
641 if (RT_SUCCESS (rc))
642 {
643 rc = vboxClipboardInit(&gCtx);
644 if (RT_SUCCESS (rc))
645 {
646 /* Always start the thread for host messages. */
647 *pfStartThread = true;
648 }
649 else
650 {
651 VbglR3ClipboardDisconnect(gCtx.u32ClientID);
652 }
653 }
654
655 if (RT_SUCCESS(rc))
656 *ppInstance = &gCtx;
657 return rc;
658}
659
660unsigned __stdcall VBoxClipboardThread(void *pInstance)
661{
662 LogFlowFunc(("VBoxClipboardThread\n"));
663
664 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
665 AssertPtr(pCtx);
666
667 /* The thread waits for incoming messages from the host. */
668 for (;;)
669 {
670 uint32_t u32Msg;
671 uint32_t u32Formats;
672 int rc = VbglR3ClipboardGetHostMsg(pCtx->u32ClientID, &u32Msg, &u32Formats);
673 if (RT_FAILURE(rc))
674 {
675 LogFlowFunc(("VBoxClipboardThread: Failed to call the driver for host message! rc = %Rrc\n", rc));
676 if (rc == VERR_INTERRUPTED)
677 {
678 /* Wait for termination event. */
679 WaitForSingleObject(pCtx->pEnv->hStopEvent, INFINITE);
680 break;
681 }
682 /* Wait a bit before retrying. */
683 AssertPtr(pCtx->pEnv);
684 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
685 {
686 break;
687 }
688 continue;
689 }
690 else
691 {
692 LogFlowFunc(("VBoxClipboardThread: VbglR3ClipboardGetHostMsg u32Msg = %ld, u32Formats = %ld\n", u32Msg, u32Formats));
693 switch (u32Msg)
694 {
695 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
696 {
697 /* The host has announced available clipboard formats.
698 * Forward the information to the window, so it can later
699 * respond to WM_RENDERFORMAT message. */
700 ::PostMessage (pCtx->hwnd, WM_USER, 0, u32Formats);
701 } break;
702
703 case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
704 {
705 /* The host needs data in the specified format. */
706 ::PostMessage (pCtx->hwnd, WM_USER + 1, 0, u32Formats);
707 } break;
708
709 case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
710 {
711 /* The host is terminating. */
712 rc = VERR_INTERRUPTED;
713 } break;
714
715 default:
716 {
717 LogFlowFunc(("VBoxClipboardThread: Unsupported message from host! Message = %ld\n", u32Msg));
718 }
719 }
720 }
721 }
722 return 0;
723}
724
725void VBoxClipboardDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
726{
727 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
728 if (pCtx != &gCtx)
729 {
730 LogFlowFunc(("VBoxClipboardDestroy: invalid instance %p (our = %p)!\n", pCtx, &gCtx));
731 pCtx = &gCtx;
732 }
733
734 vboxClipboardDestroy (pCtx);
735 VbglR3ClipboardDisconnect(pCtx->u32ClientID);
736 memset (pCtx, 0, sizeof (*pCtx));
737 return;
738}
739
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette