VirtualBox

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

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

Shared clipboard. Changelog update.

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