VirtualBox

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

Last change on this file since 2412 was 2386, checked in by vboxsync, 18 years ago

Clipboard RDP channel

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.8 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 dprintf (("vboxClipboardChanged: format 0x%08X\n", format));
323 switch (format)
324 {
325 case CF_UNICODETEXT:
326 case CF_TEXT:
327 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
328 break;
329
330 case CF_DIB:
331 case CF_BITMAP:
332 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
333 break;
334
335 default:
336 break;
337 }
338 }
339
340 CloseClipboard ();
341
342 vboxClipboardReportFormats (pCtx, u32Formats);
343 }
344}
345
346static LRESULT vboxClipboardProcessMsg(VBOXCLIPBOARDCONTEXT *pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
347{
348 LRESULT rc = 0;
349
350 switch (msg)
351 {
352 case WM_CHANGECBCHAIN:
353 {
354 HWND hwndRemoved = (HWND)wParam;
355 HWND hwndNext = (HWND)lParam;
356
357 dprintf (("vboxClipboardProcessMsg: WM_CHANGECBCHAIN: hwndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));
358
359 if (hwndRemoved == pCtx->hwndNextInChain)
360 {
361 /* The window that was next to our in the chain is being removed.
362 * Relink to the new next window.
363 */
364 pCtx->hwndNextInChain = hwndNext;
365 }
366 else
367 {
368 if (pCtx->hwndNextInChain)
369 {
370 /* Pass the message further. */
371 rc = SendMessage (pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam);
372 }
373 }
374 } break;
375
376 case WM_DRAWCLIPBOARD:
377 {
378 dprintf (("vboxClipboardProcessMsg: WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));
379
380 if (!pCtx->fAnnouncing)
381 {
382 vboxClipboardChanged (pCtx);
383 }
384
385 /* Pass the message to next windows in the clipboard chain. */
386 rc = SendMessage (pCtx->hwndNextInChain, msg, wParam, lParam);
387 } break;
388
389 case WM_CLOSE:
390 {
391 /* Do nothing. Ignore the message. */
392 } break;
393
394 case WM_RENDERFORMAT:
395 {
396 /* Insert the requested clipboard format data into the clipboard. */
397 uint32_t u32Format = 0;
398
399 UINT format = (UINT)wParam;
400
401 switch (format)
402 {
403 case CF_UNICODETEXT:
404 u32Format |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
405 break;
406
407 case CF_DIB:
408 u32Format |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
409 break;
410
411 default:
412 break;
413 }
414
415 if (u32Format == 0)
416 {
417 /* Unsupported clipboard format is requested. */
418 EmptyClipboard ();
419 }
420 else
421 {
422 const uint32_t cbPrealloc = 4096;
423 uint32_t cb = 0;
424
425 /* Preallocate a buffer, most of small text transfers will fit into it. */
426 HANDLE hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
427 dprintf(("hMem %p\n", hMem));
428
429 if (hMem)
430 {
431 void *pMem = GlobalLock (hMem);
432 dprintf(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
433
434 if (pMem)
435 {
436 /* Read the host data to the preallocated buffer. */
437 int vboxrc = vboxClipboardReadData (pCtx, u32Format, pMem, cbPrealloc, &cb);
438 dprintf(("vboxClipboardReadData vboxrc %d\n", vboxrc));
439
440 if (VBOX_SUCCESS (rc))
441 {
442 if (cb > cbPrealloc)
443 {
444 GlobalUnlock (hMem);
445
446 /* The preallocated buffer is too small, adjust the size. */
447 hMem = GlobalReAlloc (hMem, cb, 0);
448 dprintf(("hMem %p\n", hMem));
449
450 if (hMem)
451 {
452 pMem = GlobalLock (hMem);
453 dprintf(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
454
455 if (pMem)
456 {
457 /* Read the host data to the preallocated buffer. */
458 uint32_t cbNew = 0;
459 vboxrc = vboxClipboardReadData (pCtx, u32Format, pMem, cb, &cbNew);
460 dprintf(("vboxClipboardReadData vboxrc %d, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));
461
462 if (VBOX_SUCCESS (vboxrc) && cbNew <= cb)
463 {
464 cb = cbNew;
465 }
466 else
467 {
468 GlobalUnlock (pMem);
469 GlobalFree (hMem);
470 hMem = NULL;
471 }
472 }
473 else
474 {
475 GlobalFree (hMem);
476 hMem = NULL;
477 }
478 }
479 }
480
481 if (hMem)
482 {
483 /* pMem is the address of the data. cb is the size of returned data. */
484 /* Verify the size of returned text. */
485 if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
486 {
487 cb = (lstrlenW((LPWSTR)pMem) + 1) * 2;
488 }
489
490 GlobalUnlock (hMem);
491
492 hMem = GlobalReAlloc (hMem, cb, 0);
493 dprintf(("hMem %p\n", hMem));
494
495 if (hMem)
496 {
497 /* 'hMem' contains the host clipboard data.
498 * size is 'cb' and format is 'format'.
499 */
500 HANDLE hClip = SetClipboardData (format, hMem);
501 dprintf(("WM_RENDERFORMAT hClip %p\n", hClip));
502
503 if (hClip)
504 {
505 /* The hMem ownership has gone to the system. Finish the processing. */
506 break;
507 }
508
509 /* Cleanup follows. */
510 }
511 }
512 }
513
514 if (hMem)
515 {
516 GlobalUnlock (hMem);
517 }
518 }
519
520 if (hMem)
521 {
522 GlobalFree (hMem);
523 }
524 }
525
526 /* Something went wrong. */
527 EmptyClipboard ();
528 }
529 } break;
530
531 case WM_RENDERALLFORMATS:
532 {
533 /* Do nothing. The clipboard formats will be unavailable now, because the
534 * windows is to be destroyed and therefore the guest side becomes inactive.
535 */
536 if (OpenClipboard (hwnd))
537 {
538 EmptyClipboard();
539
540 CloseClipboard();
541 }
542 } break;
543
544 case WM_USER:
545 {
546 /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
547 uint32_t u32Formats = (uint32_t)lParam;
548
549 /* Prevent the WM_DRAWCLIPBOARD processing. */
550 pCtx->fAnnouncing = true;
551
552 if (OpenClipboard (hwnd))
553 {
554 EmptyClipboard();
555
556 HANDLE hClip = NULL;
557
558 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
559 {
560 dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
561 hClip = SetClipboardData (CF_UNICODETEXT, NULL);
562 }
563
564 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
565 {
566 dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
567 hClip = SetClipboardData (CF_DIB, NULL);
568 }
569
570 CloseClipboard();
571
572 dprintf(("window proc WM_USER: hClip %p\n", hClip));
573 }
574 else
575 {
576 dprintf(("window proc WM_USER: failed to open clipboard\n"));
577 }
578
579 pCtx->fAnnouncing = false;
580 } break;
581
582 case WM_USER + 1:
583 {
584 /* Send data in the specified format to the host. */
585 uint32_t u32Formats = (uint32_t)lParam;
586
587 HANDLE hClip = NULL;
588
589 if (OpenClipboard (hwnd))
590 {
591 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
592 {
593 hClip = GetClipboardData (CF_DIB);
594
595 if (hClip != NULL)
596 {
597 LPVOID lp = GlobalLock (hClip);
598
599 if (lp != NULL)
600 {
601 dprintf(("CF_DIB\n"));
602
603 vboxClipboardWriteData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
604 lp, GlobalSize (hClip));
605
606 GlobalUnlock(hClip);
607 }
608 else
609 {
610 hClip = NULL;
611 }
612 }
613 }
614 else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
615 {
616 hClip = GetClipboardData(CF_UNICODETEXT);
617
618 if (hClip != NULL)
619 {
620 LPWSTR uniString = (LPWSTR)GlobalLock (hClip);
621
622 if (uniString != NULL)
623 {
624 dprintf(("CF_UNICODETEXT\n"));
625
626 vboxClipboardWriteData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
627 uniString, (lstrlenW (uniString) + 1) * 2);
628
629 GlobalUnlock(hClip);
630 }
631 else
632 {
633 hClip = NULL;
634 }
635 }
636 }
637
638 CloseClipboard ();
639 }
640
641 if (hClip == NULL)
642 {
643 /* Requested clipboard format is not available, send empty data. */
644 vboxClipboardWriteData (pCtx, 0, NULL, 0);
645 }
646 } break;
647
648 default:
649 {
650 rc = DefWindowProc (hwnd, msg, wParam, lParam);
651 }
652 }
653
654 return rc;
655}
656
657static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
658
659static int vboxClipboardInit (VBOXCLIPBOARDCONTEXT *pCtx)
660{
661 int rc = VINF_SUCCESS;
662
663 /* Register the Window Class. */
664 WNDCLASS wc;
665
666 wc.style = CS_NOCLOSE;
667 wc.lpfnWndProc = vboxClipboardWndProc;
668 wc.cbClsExtra = 0;
669 wc.cbWndExtra = 0;
670 wc.hInstance = pCtx->pEnv->hInstance;
671 wc.hIcon = NULL;
672 wc.hCursor = NULL;
673 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
674 wc.lpszMenuName = NULL;
675 wc.lpszClassName = gachWindowClassName;
676
677 pCtx->atomWindowClass = RegisterClass (&wc);
678
679 if (pCtx->atomWindowClass == 0)
680 {
681 rc = VERR_NOT_SUPPORTED;
682 }
683 else
684 {
685 /* Create the window. */
686 pCtx->hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
687 gachWindowClassName, gachWindowClassName,
688 WS_POPUPWINDOW,
689 -200, -200, 100, 100, NULL, NULL, pCtx->pEnv->hInstance, NULL);
690
691 if (pCtx->hwnd == NULL)
692 {
693 rc = VERR_NOT_SUPPORTED;
694 }
695 else
696 {
697 SetWindowPos(pCtx->hwnd, HWND_TOPMOST, -200, -200, 0, 0,
698 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
699
700 pCtx->hwndNextInChain = SetClipboardViewer (pCtx->hwnd);
701 }
702 }
703
704 return rc;
705}
706
707static void vboxClipboardDestroy (VBOXCLIPBOARDCONTEXT *pCtx)
708{
709 if (pCtx->hwnd)
710 {
711 ChangeClipboardChain (pCtx->hwnd, pCtx->hwndNextInChain);
712 pCtx->hwndNextInChain = NULL;
713
714 DestroyWindow (pCtx->hwnd);
715 pCtx->hwnd = NULL;
716 }
717
718 if (pCtx->atomWindowClass != 0)
719 {
720 UnregisterClass(gachWindowClassName, pCtx->pEnv->hInstance);
721 pCtx->atomWindowClass = 0;
722 }
723}
724
725/* Static since it is the single instance. Directly used in the windows proc. */
726static VBOXCLIPBOARDCONTEXT gCtx = { NULL };
727
728static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
729{
730 /* Forward with proper context. */
731 return vboxClipboardProcessMsg (&gCtx, hwnd, msg, wParam, lParam);
732}
733
734int VBoxClipboardInit (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
735{
736 int rc = VINF_SUCCESS;
737
738 dprintf (("VboxClipboardInit\n"));
739
740 if (gCtx.pEnv)
741 {
742 /* Clipboard was already initialized. 2 or more instances are not supported. */
743 return VERR_NOT_SUPPORTED;
744 }
745
746 memset (&gCtx, 0, sizeof (gCtx));
747
748 gCtx.pEnv = pEnv;
749
750 rc = vboxClipboardConnect (&gCtx);
751
752 if (VBOX_SUCCESS (rc))
753 {
754 rc = vboxClipboardInit (&gCtx);
755
756 dprintf (("vboxClipboardInit: rc = %d\n", rc));
757
758 if (VBOX_SUCCESS (rc))
759 {
760 /* Always start the thread for host messages. */
761 *pfStartThread = true;
762 }
763 }
764
765 if (VBOX_SUCCESS (rc))
766 {
767 *ppInstance = &gCtx;
768 }
769 else
770 {
771 vboxClipboardDisconnect (&gCtx);
772 }
773
774 return rc;
775}
776
777unsigned __stdcall VBoxClipboardThread (void *pInstance)
778{
779 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
780
781 dprintf(("VBoxClipboardThread\n"));
782
783 /* Open the new driver instance to not interfere with other callers. */
784 HANDLE hDriver = CreateFile(VBOXGUEST_DEVICE_NAME,
785 GENERIC_READ | GENERIC_WRITE,
786 FILE_SHARE_READ | FILE_SHARE_WRITE,
787 NULL,
788 OPEN_EXISTING,
789 FILE_ATTRIBUTE_NORMAL,
790 NULL);
791
792 /* The thread waits for incoming messages from the host. */
793 for (;;)
794 {
795 VBoxClipboardGetHostMsg parms;
796
797 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, pCtx);
798
799 VBoxHGCMParmUInt32Set (&parms.msg, 0);
800 VBoxHGCMParmUInt32Set (&parms.formats, 0);
801
802 DWORD cbReturned;
803
804 if (!DeviceIoControl (hDriver,
805 IOCTL_VBOXGUEST_HGCM_CALL,
806 &parms, sizeof (parms),
807 &parms, sizeof (parms),
808 &cbReturned,
809 NULL))
810 {
811 dprintf(("Failed to call the driver for host message.\n"));
812
813 /* Wait a bit before retrying. */
814 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
815 {
816 break;
817 }
818
819 continue;
820 }
821
822 int rc = parms.hdr.result;
823
824 if (VBOX_SUCCESS (rc))
825 {
826 uint32_t u32Msg;
827 uint32_t u32Formats;
828
829 rc = VBoxHGCMParmUInt32Get (&parms.msg, &u32Msg);
830
831 if (VBOX_SUCCESS (rc))
832 {
833 rc = VBoxHGCMParmUInt32Get (&parms.formats, &u32Formats);
834
835 if (VBOX_SUCCESS (rc))
836 {
837 dprintf(("vboxClipboardHostEvent u32Msg %d, u32Formats %d\n", u32Msg, u32Formats));
838
839 switch (u32Msg)
840 {
841 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
842 {
843 /* The host has announced available clipboard formats.
844 * Forward the information to the window, so it can later
845 * respond to WM_RENDERFORMAT message.
846 */
847 ::PostMessage (pCtx->hwnd, WM_USER, 0, u32Formats);
848 } break;
849 case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
850 {
851 /* The host needs data in the specified format.
852 */
853 ::PostMessage (pCtx->hwnd, WM_USER + 1, 0, u32Formats);
854 } break;
855 case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
856 {
857 /* The host is terminating.
858 */
859 rc = VERR_INTERRUPTED;
860 } break;
861 default:
862 {
863 dprintf(("Unsupported message from host!!!"));
864 }
865 }
866 }
867 }
868 }
869
870 if (rc == VERR_INTERRUPTED)
871 {
872 /* Wait for termination event. */
873 WaitForSingleObject(pCtx->pEnv->hStopEvent, INFINITE);
874 break;
875 }
876
877 if (VBOX_FAILURE (rc))
878 {
879 /* Wait a bit before retrying. */
880 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
881 {
882 break;
883 }
884
885 continue;
886 }
887
888 dprintf(("processed host event rc = %d\n", rc));
889 }
890
891 CloseHandle (hDriver);
892
893 return 0;
894}
895
896void VBoxClipboardDestroy (const VBOXSERVICEENV *pEnv, void *pInstance)
897{
898 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
899
900 if (pCtx != &gCtx)
901 {
902 dprintf(("VBoxClipboardDestroy: invalid instance %p (our %p)!!!\n", pCtx, &gCtx));
903
904 pCtx = &gCtx;
905 }
906
907 vboxClipboardDestroy (pCtx);
908
909 vboxClipboardDisconnect (pCtx);
910
911 memset (pCtx, 0, sizeof (*pCtx));
912
913 return;
914}
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