VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxService/VBoxClipboard.cpp@ 2257

Last change on this file since 2257 was 1305, checked in by vboxsync, 18 years ago

Guest side of shared clipboard can receive less data than the buffer size.

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