VirtualBox

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

Last change on this file since 10541 was 10541, checked in by vboxsync, 16 years ago

Removed deprecated IOCTL namings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.5 KB
Line 
1/** @file
2 *
3 * VBoxClipboard - Shared clipboard
4 *
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#include "VBoxTray.h"
24#include <VBox/HostServices/VBoxClipboardSvc.h>
25#include "helpers.h"
26#include <iprt/asm.h>
27
28typedef struct _VBOXCLIPBOARDCONTEXT
29{
30 const VBOXSERVICEENV *pEnv;
31
32 uint32_t u32ClientID;
33
34 ATOM atomWindowClass;
35
36 HWND hwnd;
37
38 HWND hwndNextInChain;
39
40// bool fOperational;
41
42// uint32_t u32LastSentFormat;
43// uint64_t u64LastSentCRC64;
44
45} VBOXCLIPBOARDCONTEXT;
46
47
48static char gachWindowClassName[] = "VBoxSharedClipboardClass";
49
50
51#define VBOX_INIT_CALL(__a, __b, __c) do { \
52 (__a)->hdr.result = VINF_SUCCESS; \
53 (__a)->hdr.u32ClientID = (__c)->u32ClientID; \
54 (__a)->hdr.u32Function = (__b); \
55 (__a)->hdr.cParms = (sizeof (*(__a)) - sizeof ((__a)->hdr)) / sizeof (HGCMFunctionParameter); \
56} while (0)
57
58
59//static bool vboxClipboardIsSameAsLastSent (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
60// void *pv, uint32_t cb)
61//{
62// uint64_t u64CRC = RTCrc64 (pv, cb);
63//
64// if ( pCtx->u32LastSentFormat == u32Format
65// && pCtx->u64LastSentCRC64 == u64CRC)
66// {
67// return true;
68// }
69//
70// pCtx->u64LastSentCRC64 = u64CRC;
71// pCtx->u32LastSentFormat = u32Format;
72//
73// return false;
74//}
75
76static int vboxClipboardConnect (VBOXCLIPBOARDCONTEXT *pCtx)
77{
78 VBoxGuestHGCMConnectInfo info;
79
80 memset (&info, 0, sizeof (info));
81
82 info.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
83
84 strcpy (info.Loc.u.host.achName, "VBoxSharedClipboard");
85
86 DWORD cbReturned;
87
88 if (DeviceIoControl (pCtx->pEnv->hDriver,
89 VBOXGUEST_IOCTL_HGCM_CONNECT,
90 &info, sizeof (info),
91 &info, sizeof (info),
92 &cbReturned,
93 NULL))
94 {
95 if (info.result == VINF_SUCCESS)
96 {
97 pCtx->u32ClientID = info.u32ClientID;
98 }
99 }
100 else
101 {
102 info.result = VERR_NOT_SUPPORTED;
103 }
104
105 return info.result;
106}
107
108static void vboxClipboardDisconnect (VBOXCLIPBOARDCONTEXT *pCtx)
109{
110 if (pCtx->u32ClientID == 0)
111 {
112 return;
113 }
114
115 VBoxGuestHGCMDisconnectInfo info;
116
117 memset (&info, 0, sizeof (info));
118
119 info.u32ClientID = pCtx->u32ClientID;
120
121 DWORD cbReturned;
122
123 DeviceIoControl (pCtx->pEnv->hDriver,
124 VBOXGUEST_IOCTL_HGCM_DISCONNECT,
125 &info, sizeof (info),
126 &info, sizeof (info),
127 &cbReturned,
128 NULL);
129
130 return;
131}
132
133
134static void VBoxHGCMParmUInt32Set (HGCMFunctionParameter *pParm, uint32_t u32)
135{
136 pParm->type = VMMDevHGCMParmType_32bit;
137 pParm->u.value32 = u32;
138}
139
140static int VBoxHGCMParmUInt32Get (HGCMFunctionParameter *pParm, uint32_t *pu32)
141{
142 if (pParm->type == VMMDevHGCMParmType_32bit)
143 {
144 *pu32 = pParm->u.value32;
145 return VINF_SUCCESS;
146 }
147
148 return VERR_INVALID_PARAMETER;
149}
150
151static void VBoxHGCMParmPtrSet (HGCMFunctionParameter *pParm, void *pv, uint32_t cb)
152{
153 pParm->type = VMMDevHGCMParmType_LinAddr;
154 pParm->u.Pointer.size = cb;
155 pParm->u.Pointer.u.linearAddr = (uintptr_t)pv;
156}
157
158
159static int vboxCall (HANDLE hDriver, void *pvData, unsigned cbData)
160{
161 DWORD cbReturned;
162
163 if (DeviceIoControl (hDriver,
164 VBOXGUEST_IOCTL_HGCM_CALL,
165 pvData, cbData,
166 pvData, cbData,
167 &cbReturned,
168 NULL))
169 {
170 return VINF_SUCCESS;
171 }
172
173 return VERR_NOT_SUPPORTED;
174}
175
176static int vboxClipboardReportFormats (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Formats)
177{
178 VBoxClipboardFormats parms;
179
180 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_FORMATS, pCtx);
181
182 VBoxHGCMParmUInt32Set (&parms.formats, u32Formats);
183
184 int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
185
186 if (VBOX_SUCCESS (rc))
187 {
188 rc = parms.hdr.result;
189 }
190
191 return rc;
192}
193
194static int vboxClipboardReadData (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual)
195{
196 VBoxClipboardReadData parms;
197
198 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_READ_DATA, pCtx);
199
200 VBoxHGCMParmUInt32Set (&parms.format, u32Format);
201 VBoxHGCMParmPtrSet (&parms.ptr, pv, cb);
202 VBoxHGCMParmUInt32Set (&parms.size, 0);
203
204 int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
205
206 if (VBOX_SUCCESS (rc))
207 {
208 rc = parms.hdr.result;
209
210 if (VBOX_SUCCESS (rc))
211 {
212 uint32_t u32Size;
213
214 rc = VBoxHGCMParmUInt32Get (&parms.size, &u32Size);
215
216 dprintf (("vboxClipboardReadData: actual size = %d, rc = %d\n", u32Size, rc));
217
218 if (VBOX_SUCCESS (rc))
219 {
220 if (pcbActual)
221 {
222 *pcbActual = u32Size;
223 }
224 }
225 }
226 }
227
228 return rc;
229}
230
231static int vboxClipboardWriteData (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
232 void *pv, uint32_t cb)
233{
234// if (vboxClipboardIsSameAsLastSent (pCtx, u32Format, pv, cb))
235// {
236// dprintf (("vboxClipboardWriteData: The data to be sent are the same as the last sent.\n"));
237// return VINF_SUCCESS;
238// }
239
240 VBoxClipboardWriteData parms;
241
242 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA, pCtx);
243
244 VBoxHGCMParmUInt32Set (&parms.format, u32Format);
245 VBoxHGCMParmPtrSet (&parms.ptr, pv, cb);
246
247 int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
248
249 if (VBOX_SUCCESS (rc))
250 {
251 rc = parms.hdr.result;
252 }
253
254 return rc;
255}
256
257static void vboxClipboardChanged (VBOXCLIPBOARDCONTEXT *pCtx)
258{
259 /* Query list of available formats and report to host. */
260 if (OpenClipboard (pCtx->hwnd))
261 {
262 uint32_t u32Formats = 0;
263
264 UINT format = 0;
265
266 while ((format = EnumClipboardFormats (format)) != 0)
267 {
268 dprintf (("vboxClipboardChanged: format 0x%08X\n", format));
269 switch (format)
270 {
271 case CF_UNICODETEXT:
272 case CF_TEXT:
273 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
274 break;
275
276 case CF_DIB:
277 case CF_BITMAP:
278 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
279 break;
280
281 default:
282 if (format >= 0xC000)
283 {
284 TCHAR szFormatName[256];
285
286 int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
287
288 if (cActual)
289 {
290 if (strcmp (szFormatName, "HTML Format") == 0)
291 {
292 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
293 }
294 }
295 }
296 break;
297 }
298 }
299
300 CloseClipboard ();
301
302 vboxClipboardReportFormats (pCtx, u32Formats);
303 }
304}
305
306static LRESULT vboxClipboardProcessMsg(VBOXCLIPBOARDCONTEXT *pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
307{
308 LRESULT rc = 0;
309
310 switch (msg)
311 {
312 case WM_CHANGECBCHAIN:
313 {
314 HWND hwndRemoved = (HWND)wParam;
315 HWND hwndNext = (HWND)lParam;
316
317 dprintf (("vboxClipboardProcessMsg: WM_CHANGECBCHAIN: hwndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));
318
319 if (hwndRemoved == pCtx->hwndNextInChain)
320 {
321 /* The window that was next to our in the chain is being removed.
322 * Relink to the new next window.
323 */
324 pCtx->hwndNextInChain = hwndNext;
325 }
326 else
327 {
328 if (pCtx->hwndNextInChain)
329 {
330 /* Pass the message further. */
331 rc = SendMessage (pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam);
332 }
333 }
334 } break;
335
336 case WM_DRAWCLIPBOARD:
337 {
338 dprintf (("vboxClipboardProcessMsg: WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));
339
340 if (GetClipboardOwner () != hwnd)
341 {
342 /* Clipboard was updated by another application. */
343 vboxClipboardChanged (pCtx);
344 }
345
346 /* Pass the message to next windows in the clipboard chain. */
347 rc = SendMessage (pCtx->hwndNextInChain, msg, wParam, lParam);
348 } break;
349
350 case WM_CLOSE:
351 {
352 /* Do nothing. Ignore the message. */
353 } break;
354
355 case WM_RENDERFORMAT:
356 {
357 /* Insert the requested clipboard format data into the clipboard. */
358 uint32_t u32Format = 0;
359
360 UINT format = (UINT)wParam;
361
362 dprintf (("vboxClipboardProcessMsg: WM_RENDERFORMAT, format %x\n", format));
363
364 switch (format)
365 {
366 case CF_UNICODETEXT:
367 u32Format |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
368 break;
369
370 case CF_DIB:
371 u32Format |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
372 break;
373
374 default:
375 if (format >= 0xC000)
376 {
377 TCHAR szFormatName[256];
378
379 int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
380
381 if (cActual)
382 {
383 if (strcmp (szFormatName, "HTML Format") == 0)
384 {
385 u32Format |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
386 }
387 }
388 }
389 break;
390 }
391
392 if (u32Format == 0)
393 {
394 /* Unsupported clipboard format is requested. */
395 EmptyClipboard ();
396 }
397 else
398 {
399 const uint32_t cbPrealloc = 4096;
400 uint32_t cb = 0;
401
402 /* Preallocate a buffer, most of small text transfers will fit into it. */
403 HANDLE hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
404 dprintf(("hMem %p\n", hMem));
405
406 if (hMem)
407 {
408 void *pMem = GlobalLock (hMem);
409 dprintf(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
410
411 if (pMem)
412 {
413 /* Read the host data to the preallocated buffer. */
414 int vboxrc = vboxClipboardReadData (pCtx, u32Format, pMem, cbPrealloc, &cb);
415 dprintf(("vboxClipboardReadData vboxrc %d\n", vboxrc));
416
417 if (VBOX_SUCCESS (rc))
418 {
419 if (cb > cbPrealloc)
420 {
421 GlobalUnlock (hMem);
422
423 /* The preallocated buffer is too small, adjust the size. */
424 hMem = GlobalReAlloc (hMem, cb, 0);
425 dprintf(("hMem %p\n", hMem));
426
427 if (hMem)
428 {
429 pMem = GlobalLock (hMem);
430 dprintf(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
431
432 if (pMem)
433 {
434 /* Read the host data to the preallocated buffer. */
435 uint32_t cbNew = 0;
436 vboxrc = vboxClipboardReadData (pCtx, u32Format, pMem, cb, &cbNew);
437 dprintf(("vboxClipboardReadData vboxrc %d, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));
438
439 if (VBOX_SUCCESS (vboxrc) && cbNew <= cb)
440 {
441 cb = cbNew;
442 }
443 else
444 {
445 GlobalUnlock (pMem);
446 GlobalFree (hMem);
447 hMem = NULL;
448 }
449 }
450 else
451 {
452 GlobalFree (hMem);
453 hMem = NULL;
454 }
455 }
456 }
457
458 if (hMem)
459 {
460 /* pMem is the address of the data. cb is the size of returned data. */
461 /* Verify the size of returned text. */
462 if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
463 {
464 cb = (lstrlenW((LPWSTR)pMem) + 1) * 2;
465 }
466
467 GlobalUnlock (hMem);
468
469 hMem = GlobalReAlloc (hMem, cb, 0);
470 dprintf(("hMem %p\n", hMem));
471
472 if (hMem)
473 {
474 /* 'hMem' contains the host clipboard data.
475 * size is 'cb' and format is 'format'.
476 */
477 HANDLE hClip = SetClipboardData (format, hMem);
478 dprintf(("WM_RENDERFORMAT hClip %p\n", hClip));
479
480 if (hClip)
481 {
482 /* The hMem ownership has gone to the system. Finish the processing. */
483 break;
484 }
485
486 /* Cleanup follows. */
487 }
488 }
489 }
490
491 if (hMem)
492 {
493 GlobalUnlock (hMem);
494 }
495 }
496
497 if (hMem)
498 {
499 GlobalFree (hMem);
500 }
501 }
502
503 /* Something went wrong. */
504 EmptyClipboard ();
505 }
506 } break;
507
508 case WM_RENDERALLFORMATS:
509 {
510 /* Do nothing. The clipboard formats will be unavailable now, because the
511 * windows is to be destroyed and therefore the guest side becomes inactive.
512 */
513 if (OpenClipboard (hwnd))
514 {
515 EmptyClipboard();
516
517 CloseClipboard();
518 }
519 } break;
520
521 case WM_USER:
522 {
523 /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
524 uint32_t u32Formats = (uint32_t)lParam;
525
526 if (OpenClipboard (hwnd))
527 {
528 EmptyClipboard();
529
530 HANDLE hClip = NULL;
531
532 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
533 {
534 dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
535
536 hClip = SetClipboardData (CF_UNICODETEXT, NULL);
537 }
538
539 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
540 {
541 dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
542
543 hClip = SetClipboardData (CF_DIB, NULL);
544 }
545
546 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
547 {
548 UINT format = RegisterClipboardFormat ("HTML Format");
549 dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_HTML 0x%04X\n", format));
550 if (format != 0)
551 {
552 hClip = SetClipboardData (format, NULL);
553 }
554 }
555
556 CloseClipboard();
557
558 dprintf(("window proc WM_USER: hClip %p, err %d\n", hClip, GetLastError ()));
559 }
560 else
561 {
562 dprintf(("window proc WM_USER: failed to open clipboard\n"));
563 }
564 } break;
565
566 case WM_USER + 1:
567 {
568 /* Send data in the specified format to the host. */
569 uint32_t u32Formats = (uint32_t)lParam;
570
571 HANDLE hClip = NULL;
572
573 if (OpenClipboard (hwnd))
574 {
575 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
576 {
577 hClip = GetClipboardData (CF_DIB);
578
579 if (hClip != NULL)
580 {
581 LPVOID lp = GlobalLock (hClip);
582
583 if (lp != NULL)
584 {
585 dprintf(("CF_DIB\n"));
586
587 vboxClipboardWriteData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
588 lp, GlobalSize (hClip));
589
590 GlobalUnlock(hClip);
591 }
592 else
593 {
594 hClip = NULL;
595 }
596 }
597 }
598 else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
599 {
600 hClip = GetClipboardData(CF_UNICODETEXT);
601
602 if (hClip != NULL)
603 {
604 LPWSTR uniString = (LPWSTR)GlobalLock (hClip);
605
606 if (uniString != NULL)
607 {
608 dprintf(("CF_UNICODETEXT\n"));
609
610 vboxClipboardWriteData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
611 uniString, (lstrlenW (uniString) + 1) * 2);
612
613 GlobalUnlock(hClip);
614 }
615 else
616 {
617 hClip = NULL;
618 }
619 }
620 }
621 else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
622 {
623 UINT format = RegisterClipboardFormat ("HTML Format");
624
625 if (format != 0)
626 {
627 hClip = GetClipboardData (format);
628
629 if (hClip != NULL)
630 {
631 LPVOID lp = GlobalLock (hClip);
632
633 if (lp != NULL)
634 {
635 dprintf(("CF_HTML\n"));
636
637 vboxClipboardWriteData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_HTML,
638 lp, GlobalSize (hClip));
639
640 GlobalUnlock(hClip);
641 }
642 else
643 {
644 hClip = NULL;
645 }
646 }
647 }
648 }
649
650 CloseClipboard ();
651 }
652
653 if (hClip == NULL)
654 {
655 /* Requested clipboard format is not available, send empty data. */
656 vboxClipboardWriteData (pCtx, 0, NULL, 0);
657 }
658 } break;
659
660 default:
661 {
662 rc = DefWindowProc (hwnd, msg, wParam, lParam);
663 }
664 }
665
666 return rc;
667}
668
669static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
670
671static int vboxClipboardInit (VBOXCLIPBOARDCONTEXT *pCtx)
672{
673 int rc = VINF_SUCCESS;
674
675 /* Register the Window Class. */
676 WNDCLASS wc;
677
678 wc.style = CS_NOCLOSE;
679 wc.lpfnWndProc = vboxClipboardWndProc;
680 wc.cbClsExtra = 0;
681 wc.cbWndExtra = 0;
682 wc.hInstance = pCtx->pEnv->hInstance;
683 wc.hIcon = NULL;
684 wc.hCursor = NULL;
685 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
686 wc.lpszMenuName = NULL;
687 wc.lpszClassName = gachWindowClassName;
688
689 pCtx->atomWindowClass = RegisterClass (&wc);
690
691 if (pCtx->atomWindowClass == 0)
692 {
693 rc = VERR_NOT_SUPPORTED;
694 }
695 else
696 {
697 /* Create the window. */
698 pCtx->hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
699 gachWindowClassName, gachWindowClassName,
700 WS_POPUPWINDOW,
701 -200, -200, 100, 100, NULL, NULL, pCtx->pEnv->hInstance, NULL);
702
703 if (pCtx->hwnd == NULL)
704 {
705 rc = VERR_NOT_SUPPORTED;
706 }
707 else
708 {
709 SetWindowPos(pCtx->hwnd, HWND_TOPMOST, -200, -200, 0, 0,
710 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
711
712 pCtx->hwndNextInChain = SetClipboardViewer (pCtx->hwnd);
713 }
714 }
715
716 return rc;
717}
718
719static void vboxClipboardDestroy (VBOXCLIPBOARDCONTEXT *pCtx)
720{
721 if (pCtx->hwnd)
722 {
723 ChangeClipboardChain (pCtx->hwnd, pCtx->hwndNextInChain);
724 pCtx->hwndNextInChain = NULL;
725
726 DestroyWindow (pCtx->hwnd);
727 pCtx->hwnd = NULL;
728 }
729
730 if (pCtx->atomWindowClass != 0)
731 {
732 UnregisterClass(gachWindowClassName, pCtx->pEnv->hInstance);
733 pCtx->atomWindowClass = 0;
734 }
735}
736
737/* Static since it is the single instance. Directly used in the windows proc. */
738static VBOXCLIPBOARDCONTEXT gCtx = { NULL };
739
740static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
741{
742 /* Forward with proper context. */
743 return vboxClipboardProcessMsg (&gCtx, hwnd, msg, wParam, lParam);
744}
745
746int VBoxClipboardInit (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
747{
748 int rc = VINF_SUCCESS;
749
750 dprintf (("VboxClipboardInit\n"));
751
752 if (gCtx.pEnv)
753 {
754 /* Clipboard was already initialized. 2 or more instances are not supported. */
755 return VERR_NOT_SUPPORTED;
756 }
757
758 memset (&gCtx, 0, sizeof (gCtx));
759
760 gCtx.pEnv = pEnv;
761
762 rc = vboxClipboardConnect (&gCtx);
763
764 if (VBOX_SUCCESS (rc))
765 {
766 rc = vboxClipboardInit (&gCtx);
767
768 dprintf (("vboxClipboardInit: rc = %d\n", rc));
769
770 if (VBOX_SUCCESS (rc))
771 {
772 /* Always start the thread for host messages. */
773 *pfStartThread = true;
774 }
775 }
776
777 if (VBOX_SUCCESS (rc))
778 {
779 *ppInstance = &gCtx;
780 }
781 else
782 {
783 vboxClipboardDisconnect (&gCtx);
784 }
785
786 return rc;
787}
788
789unsigned __stdcall VBoxClipboardThread (void *pInstance)
790{
791 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
792
793 dprintf(("VBoxClipboardThread\n"));
794
795 /* Open the new driver instance to not interfere with other callers. */
796 HANDLE hDriver = CreateFile(VBOXGUEST_DEVICE_NAME,
797 GENERIC_READ | GENERIC_WRITE,
798 FILE_SHARE_READ | FILE_SHARE_WRITE,
799 NULL,
800 OPEN_EXISTING,
801 FILE_ATTRIBUTE_NORMAL,
802 NULL);
803
804 /* The thread waits for incoming messages from the host. */
805 for (;;)
806 {
807 VBoxClipboardGetHostMsg parms;
808
809 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, pCtx);
810
811 VBoxHGCMParmUInt32Set (&parms.msg, 0);
812 VBoxHGCMParmUInt32Set (&parms.formats, 0);
813
814 DWORD cbReturned;
815
816 if (!DeviceIoControl (hDriver,
817 VBOXGUEST_IOCTL_HGCM_CALL,
818 &parms, sizeof (parms),
819 &parms, sizeof (parms),
820 &cbReturned,
821 NULL))
822 {
823 dprintf(("Failed to call the driver for host message.\n"));
824
825 /* Wait a bit before retrying. */
826 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
827 {
828 break;
829 }
830
831 continue;
832 }
833
834 int rc = parms.hdr.result;
835
836 if (VBOX_SUCCESS (rc))
837 {
838 uint32_t u32Msg;
839 uint32_t u32Formats;
840
841 rc = VBoxHGCMParmUInt32Get (&parms.msg, &u32Msg);
842
843 if (VBOX_SUCCESS (rc))
844 {
845 rc = VBoxHGCMParmUInt32Get (&parms.formats, &u32Formats);
846
847 if (VBOX_SUCCESS (rc))
848 {
849 dprintf(("vboxClipboardHostEvent u32Msg %d, u32Formats %d\n", u32Msg, u32Formats));
850
851 switch (u32Msg)
852 {
853 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
854 {
855 /* The host has announced available clipboard formats.
856 * Forward the information to the window, so it can later
857 * respond to WM_RENDERFORMAT message.
858 */
859 ::PostMessage (pCtx->hwnd, WM_USER, 0, u32Formats);
860 } break;
861 case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
862 {
863 /* The host needs data in the specified format.
864 */
865 ::PostMessage (pCtx->hwnd, WM_USER + 1, 0, u32Formats);
866 } break;
867 case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
868 {
869 /* The host is terminating.
870 */
871 rc = VERR_INTERRUPTED;
872 } break;
873 default:
874 {
875 dprintf(("Unsupported message from host!!!"));
876 }
877 }
878 }
879 }
880 }
881
882 if (rc == VERR_INTERRUPTED)
883 {
884 /* Wait for termination event. */
885 WaitForSingleObject(pCtx->pEnv->hStopEvent, INFINITE);
886 break;
887 }
888
889 if (VBOX_FAILURE (rc))
890 {
891 /* Wait a bit before retrying. */
892 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
893 {
894 break;
895 }
896
897 continue;
898 }
899
900 dprintf(("processed host event rc = %d\n", rc));
901 }
902
903 CloseHandle (hDriver);
904
905 return 0;
906}
907
908void VBoxClipboardDestroy (const VBOXSERVICEENV *pEnv, void *pInstance)
909{
910 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
911
912 if (pCtx != &gCtx)
913 {
914 dprintf(("VBoxClipboardDestroy: invalid instance %p (our %p)!!!\n", pCtx, &gCtx));
915
916 pCtx = &gCtx;
917 }
918
919 vboxClipboardDestroy (pCtx);
920
921 vboxClipboardDisconnect (pCtx);
922
923 memset (pCtx, 0, sizeof (*pCtx));
924
925 return;
926}
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