VirtualBox

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

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

Add guest services code for Windows.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.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
57typedef struct _VBOXCLIPBOARDCONTEXT
58{
59 const VBOXSERVICEENV *pEnv;
60
61 uint32_t u32ClientID;
62
63 uint32_t u32Mode;
64
65 ATOM atomWindowClass;
66
67 HWND hwnd;
68
69 HWND hwndNextInChain;
70
71 HANDLE hHostEvent;
72
73 bool fOperational;
74
75 uint32_t u32LastSentFormat;
76 uint64_t u64LastSentCRC64;
77
78} VBOXCLIPBOARDCONTEXT;
79
80static char gachWindowClassName[] = "VBoxSharedClipboardClass";
81
82#define VBOX_INIT_CALL(a, b) do { \
83 (a)->hdr.result = VINF_SUCCESS; \
84 (a)->hdr.u32ClientID = pCtx->u32ClientID; \
85 (a)->hdr.u32Function = b; \
86 (a)->hdr.cParms = (sizeof (*a) - sizeof ((a)->hdr)) / sizeof (HGCMFunctionParameter); \
87} while (0)
88
89static bool vboxClipboardIsSameAsLastSent (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
90 void *pv, uint32_t cb)
91{
92 uint64_t u64CRC = RTCrc64 (pv, cb);
93
94 if ( pCtx->u32LastSentFormat == u32Format
95 && pCtx->u64LastSentCRC64 == u64CRC)
96 {
97 return true;
98 }
99
100 pCtx->u64LastSentCRC64 = u64CRC;
101 pCtx->u32LastSentFormat = u32Format;
102
103 return false;
104}
105
106static int vboxClipboardConnect (VBOXCLIPBOARDCONTEXT *pCtx)
107{
108 VBoxGuestHGCMConnectInfo info;
109
110 memset (&info, 0, sizeof (info));
111
112 info.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
113
114 strcpy (info.Loc.u.host.achName, "VBoxSharedClipboard");
115
116 DWORD cbReturned;
117
118 if (DeviceIoControl (pCtx->pEnv->hDriver,
119 IOCTL_VBOXGUEST_HGCM_CONNECT,
120 &info, sizeof (info),
121 &info, sizeof (info),
122 &cbReturned,
123 NULL))
124 {
125 if (info.result == VINF_SUCCESS)
126 {
127 pCtx->u32ClientID = info.u32ClientID;
128 }
129 }
130 else
131 {
132 info.result = VERR_NOT_SUPPORTED;
133 }
134
135 return info.result;
136}
137
138static void vboxClipboardDisconnect (VBOXCLIPBOARDCONTEXT *pCtx)
139{
140 if (pCtx->u32ClientID == 0)
141 {
142 return;
143 }
144
145 VBoxGuestHGCMDisconnectInfo info;
146
147 memset (&info, 0, sizeof (info));
148
149 info.u32ClientID = pCtx->u32ClientID;
150
151 DWORD cbReturned;
152
153 DeviceIoControl (pCtx->pEnv->hDriver,
154 IOCTL_VBOXGUEST_HGCM_DISCONNECT,
155 &info, sizeof (info),
156 &info, sizeof (info),
157 &cbReturned,
158 NULL);
159
160 return;
161}
162
163
164static void VBoxHGCMParmUInt32Set (HGCMFunctionParameter *pParm, uint32_t u32)
165{
166 pParm->type = VMMDevHGCMParmType_32bit;
167 pParm->u.value32 = u32;
168}
169
170static int VBoxHGCMParmUInt32Get (HGCMFunctionParameter *pParm, uint32_t *pu32)
171{
172 if (pParm->type == VMMDevHGCMParmType_32bit)
173 {
174 *pu32 = pParm->u.value32;
175 return VINF_SUCCESS;
176 }
177
178 return VERR_INVALID_PARAMETER;
179}
180
181static void VBoxHGCMParmPtrSet (HGCMFunctionParameter *pParm, void *pv, uint32_t cb)
182{
183 pParm->type = VMMDevHGCMParmType_LinAddr;
184 pParm->u.Pointer.size = cb;
185 pParm->u.Pointer.u.linearAddr = (VBOXGCPTR)pv;
186}
187
188
189static int vboxCall (HANDLE hDriver, void *pvData, unsigned cbData)
190{
191 DWORD cbReturned;
192
193 if (DeviceIoControl (hDriver,
194 IOCTL_VBOXGUEST_HGCM_CALL,
195 pvData, cbData,
196 pvData, cbData,
197 &cbReturned,
198 NULL))
199 {
200 return VINF_SUCCESS;
201 }
202
203 return VERR_NOT_SUPPORTED;
204}
205
206static int vboxClipboardQueryMode (VBOXCLIPBOARDCONTEXT *pCtx)
207{
208 VBoxClipboardQueryMode parms;
209
210 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_QUERY_MODE);
211
212 VBoxHGCMParmUInt32Set (&parms.mode, 0);
213
214 int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
215
216 if (VBOX_SUCCESS (rc))
217 {
218 rc = parms.hdr.result;
219
220 if (VBOX_SUCCESS (rc))
221 {
222 rc = VBoxHGCMParmUInt32Get (&parms.mode, &pCtx->u32Mode);
223
224 dprintf (("vboxClipboardQueryMode: Mode = %d, rc = %d\n", pCtx->u32Mode, rc));
225 }
226 }
227
228 return rc;
229}
230
231static int vboxClipboardHostEventCancel (VBOXCLIPBOARDCONTEXT *pCtx)
232{
233 VBoxClipboardHostEventCancel parms;
234
235 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_CANCEL);
236
237 int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
238
239 if (VBOX_SUCCESS (rc))
240 {
241 rc = parms.hdr.result;
242 }
243
244 return rc;
245}
246
247static int vboxClipboardHostEventRead (VBOXCLIPBOARDCONTEXT *pCtx, void *pv, uint32_t cb)
248{
249 if (!VirtualLock (pv, cb))
250 {
251 dprintf (("vboxClipboardHostEventRead: VirtualLock failed\n"));
252 return VERR_NOT_SUPPORTED;
253 }
254
255 VBoxClipboardHostEventRead parms;
256
257 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_READ);
258
259 VBoxHGCMParmPtrSet (&parms.ptr, pv, cb);
260
261 int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
262
263 if (VBOX_SUCCESS (rc))
264 {
265 rc = parms.hdr.result;
266 }
267
268 VirtualUnlock (pv, cb);
269
270 return rc;
271}
272
273static int vboxClipboardSendData (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
274 void *pv, uint32_t cb)
275{
276 if (vboxClipboardIsSameAsLastSent (pCtx, u32Format, pv, cb))
277 {
278 dprintf (("vboxClipboardSendData: The data to be sent are the same as the last sent.\n"));
279 return VINF_SUCCESS;
280 }
281
282 if (!VirtualLock (pv, cb))
283 {
284 dprintf (("vboxClipboardSendData: VirtualLock failed\n"));
285 return VERR_NOT_SUPPORTED;
286 }
287
288 VBoxClipboardSendData parms;
289
290 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_SEND_DATA);
291
292 VBoxHGCMParmUInt32Set (&parms.format, u32Format);
293 VBoxHGCMParmPtrSet (&parms.ptr, pv, cb);
294
295 int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
296
297 if (VBOX_SUCCESS (rc))
298 {
299 rc = parms.hdr.result;
300 }
301
302 VirtualUnlock (pv, cb);
303
304 return rc;
305}
306
307
308static void vboxClipboardSendDIB (VBOXCLIPBOARDCONTEXT *pCtx)
309{
310 HANDLE hClip = GetClipboardData (CF_DIB);
311
312 if (hClip != NULL)
313 {
314 LPVOID lp = GlobalLock (hClip);
315
316 if (lp != NULL)
317 {
318 vboxClipboardSendData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
319 lp, GlobalSize (hClip));
320
321 GlobalUnlock(hClip);
322 }
323 }
324}
325
326static void vboxClipboardSendBitmap (VBOXCLIPBOARDCONTEXT *pCtx)
327{
328 /* Request DIB format anyway. The system will convert the available CF_BITMAP to CF_DIB. */
329 vboxClipboardSendDIB (pCtx);
330}
331
332static void vboxClipboardSendUnicodeText (VBOXCLIPBOARDCONTEXT *pCtx)
333{
334 HANDLE hClip = GetClipboardData(CF_UNICODETEXT);
335
336 if (hClip != NULL)
337 {
338 LPWSTR uniString = (LPWSTR)GlobalLock (hClip);
339
340 if (uniString != NULL)
341 {
342 vboxClipboardSendData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
343 uniString, (lstrlenW (uniString) + 1) * 2);
344
345 GlobalUnlock(hClip);
346 }
347 }
348}
349
350static void vboxClipboardSendText (VBOXCLIPBOARDCONTEXT *pCtx)
351{
352 /* Request UNICODE format anyway. The system will convert the available CF_TEXT to CF_UNICODE. */
353 vboxClipboardSendUnicodeText (pCtx);
354}
355
356static void vboxClipboardGuestEvent (VBOXCLIPBOARDCONTEXT *pCtx)
357{
358 if ( pCtx->u32Mode != VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
359 && pCtx->u32Mode != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
360 {
361 /* The host will not accept the clipboard data anyway. */
362 return;
363 }
364
365 if (OpenClipboard (pCtx->hwnd))
366 {
367 int cFormats = CountClipboardFormats ();
368
369 if (cFormats > 0)
370 {
371 dprintf (("vboxClipboardGuestEvent: cFormats = %d\n", cFormats));
372
373 static UINT aFormatPriorityList[] =
374 {
375 CF_UNICODETEXT,
376 CF_TEXT,
377 CF_DIB,
378 CF_BITMAP
379 };
380
381 int iFormat = GetPriorityClipboardFormat (aFormatPriorityList, ELEMENTS (aFormatPriorityList));
382
383 switch (iFormat)
384 {
385 case CF_TEXT:
386 {
387 dprintf(("CF_TEXT\n"));
388
389 vboxClipboardSendText (pCtx);
390 } break;
391
392 case CF_UNICODETEXT:
393 {
394 dprintf(("CF_UNICODETEXT\n"));
395
396 vboxClipboardSendUnicodeText (pCtx);
397 } break;
398
399 case CF_BITMAP:
400 {
401 dprintf(("CF_BITMAP\n"));
402
403 vboxClipboardSendBitmap (pCtx);
404 } break;
405
406 case CF_DIB:
407 {
408 dprintf(("CF_DIB\n"));
409
410 vboxClipboardSendDIB (pCtx);
411 } break;
412
413 default:
414 {
415 dprintf(("not supported %d\n", iFormat));
416 }
417 }
418 }
419
420 CloseClipboard ();
421 }
422}
423
424static void vboxClipboardHostEvent (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, uint32_t u32Size)
425{
426 if ( pCtx->u32Mode != VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
427 && pCtx->u32Mode != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
428 {
429 /* The guest should not accept the clipboard data anyway. */
430 vboxClipboardHostEventCancel (pCtx);
431
432 return;
433 }
434
435 dprintf(("vboxClipboardHostEvent u32Size %d\n", u32Size));
436
437 if (u32Size > 0)
438 {
439 HANDLE hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, u32Size);
440
441 dprintf(("vboxClipboardHostEvent hMem %p\n", hMem));
442
443 if (hMem)
444 {
445 void *pMem = GlobalLock (hMem);
446
447 dprintf(("vboxClipboardHostEvent pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
448
449 if (pMem)
450 {
451 /* Read the host data and cancel the transaction. */
452 int rc = vboxClipboardHostEventRead (pCtx, pMem, u32Size);
453
454 dprintf(("vboxClipboardHostEvent read %d\n", rc));
455
456 if (VBOX_SUCCESS (rc))
457 {
458 /* Data was read from the host and transaction was cancelled.
459 * Return from the code branch without calling cancel event.
460 */
461 HANDLE hClip = 0;
462
463 /* Remember the last data that goes to the clipboard.
464 * That will prevent sending the same data back to the client.
465 */
466 vboxClipboardIsSameAsLastSent (pCtx, u32Format, pMem, u32Size);
467
468 /* The memory must be unlocked before the Clipboard is closed. */
469 GlobalUnlock (hMem);
470
471 /* 'pMem' contains the host clipboard data.
472 * size is 'u32Size' and format is 'u32Format'.
473 */
474 if (OpenClipboard (pCtx->hwnd))
475 {
476 EmptyClipboard();
477
478 if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
479 {
480 dprintf(("vboxClipboardHostEvent VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
481 hClip = SetClipboardData (CF_UNICODETEXT, hMem);
482 }
483 else if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
484 {
485 dprintf(("vboxClipboardHostEvent VBOX_SHARED_CLIPBOARD_FMT_BiTMAP\n"));
486 hClip = SetClipboardData (CF_DIB, hMem);
487 }
488
489 CloseClipboard();
490
491 dprintf(("vboxClipboardHostEvent hClip %p\n", hClip));
492 }
493 else
494 {
495 dprintf(("vboxClipboardHostEvent failed to open clipboard\n"));
496 }
497
498 if (!hClip)
499 {
500 /* Failed to set the clipboard data. */
501 GlobalFree (hMem);
502 }
503 else
504 {
505 /* The hMem ownership has gone to the system. Nothing to do. */
506 }
507
508 return;
509 }
510 else
511 {
512 GlobalUnlock (hMem);
513 }
514 }
515
516 GlobalFree (hMem);
517 }
518 }
519 else
520 {
521 if (OpenClipboard (pCtx->hwnd))
522 {
523 EmptyClipboard();
524 CloseClipboard();
525 }
526 }
527
528 vboxClipboardHostEventCancel (pCtx);
529
530 return;
531}
532
533static LRESULT vboxClipboardProcessMsg(VBOXCLIPBOARDCONTEXT *pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
534{
535 LRESULT rc = 0;
536
537 switch (msg)
538 {
539 case WM_CHANGECBCHAIN:
540 {
541 HWND hwndRemoved = (HWND)wParam;
542 HWND hwndNext = (HWND)lParam;
543
544 dprintf (("vboxClipboardProcessMsg: WM_CHANGECBCHAIN: hwndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));
545
546 if (hwndRemoved == pCtx->hwndNextInChain)
547 {
548 /* The window that was next to our in the chain is being removed.
549 * Relink to the new next window.
550 */
551 pCtx->hwndNextInChain = hwndNext;
552 }
553 else
554 {
555 if (pCtx->hwndNextInChain)
556 {
557 /* Pass the message further. */
558 rc = SendMessage (pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam);
559 }
560 }
561 } break;
562
563 case WM_DRAWCLIPBOARD:
564 {
565 dprintf (("vboxClipboardProcessMsg: WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));
566
567 vboxClipboardGuestEvent (pCtx);
568
569 /* Pass the message to next windows in the clipboard chain. */
570 rc = SendMessage (pCtx->hwndNextInChain, msg, wParam, lParam);
571 } break;
572
573 case WM_CLOSE:
574 {
575 /* Do nothing. Ignore the message. */
576 } break;
577
578 default:
579 {
580 rc = DefWindowProc (hwnd, msg, wParam, lParam);
581 }
582 }
583
584 return rc;
585}
586
587static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
588
589static int vboxClipboardInit (VBOXCLIPBOARDCONTEXT *pCtx)
590{
591 int rc = VINF_SUCCESS;
592
593 /* Register the Window Class. */
594 WNDCLASS wc;
595
596 wc.style = CS_NOCLOSE;
597 wc.lpfnWndProc = vboxClipboardWndProc;
598 wc.cbClsExtra = 0;
599 wc.cbWndExtra = 0;
600 wc.hInstance = pCtx->pEnv->hInstance;
601 wc.hIcon = NULL;
602 wc.hCursor = NULL;
603 wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
604 wc.lpszMenuName = NULL;
605 wc.lpszClassName = gachWindowClassName;
606
607 pCtx->atomWindowClass = RegisterClass (&wc);
608
609 if (pCtx->atomWindowClass == 0)
610 {
611 rc = VERR_NOT_SUPPORTED;
612 }
613 else
614 {
615 /* Create the window. */
616 pCtx->hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
617 gachWindowClassName, gachWindowClassName,
618 WS_POPUPWINDOW,
619 -200, -200, 100, 100, NULL, NULL, pCtx->pEnv->hInstance, NULL);
620
621 if (pCtx->hwnd == NULL)
622 {
623 rc = VERR_NOT_SUPPORTED;
624 }
625 else
626 {
627 SetWindowPos(pCtx->hwnd, HWND_TOPMOST, -200, -200, 0, 0,
628 SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
629
630 pCtx->hwndNextInChain = SetClipboardViewer (pCtx->hwnd);
631 }
632 }
633
634 return rc;
635}
636
637static void vboxClipboardDestroy (VBOXCLIPBOARDCONTEXT *pCtx)
638{
639 if (pCtx->hwnd)
640 {
641 ChangeClipboardChain (pCtx->hwnd, pCtx->hwndNextInChain);
642 pCtx->hwndNextInChain = NULL;
643
644 DestroyWindow (pCtx->hwnd);
645 pCtx->hwnd = NULL;
646 }
647
648 if (pCtx->atomWindowClass != 0)
649 {
650 UnregisterClass(gachWindowClassName, pCtx->pEnv->hInstance);
651 pCtx->atomWindowClass = 0;
652 }
653}
654
655/* Static since it is the single instance. Directly used in the windows proc. */
656static VBOXCLIPBOARDCONTEXT gCtx = { NULL };
657
658static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
659{
660 /* Forward with proper context. */
661 return vboxClipboardProcessMsg (&gCtx, hwnd, msg, wParam, lParam);
662}
663
664int VBoxClipboardInit (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
665{
666 int rc = VINF_SUCCESS;
667
668 dprintf (("VboxClipboardInit\n"));
669
670 if (!gCtx.pEnv)
671 {
672 memset (&gCtx, 0, sizeof (gCtx));
673
674 gCtx.pEnv = pEnv;
675
676 rc = vboxClipboardConnect (&gCtx);
677
678 if (VBOX_SUCCESS (rc))
679 {
680 rc = vboxClipboardQueryMode (&gCtx);
681
682 if (VBOX_SUCCESS (rc))
683 {
684 rc = vboxClipboardInit (&gCtx);
685
686 dprintf (("vboxClipboardInit: rc = %d\n", rc));
687
688 if (VBOX_SUCCESS (rc))
689 {
690 /* Host to Guest direction requires the thread. */
691 if ( gCtx.u32Mode == VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
692 || gCtx.u32Mode == VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
693 {
694 *pfStartThread = true;
695 }
696 }
697 }
698 }
699 }
700
701 if (VBOX_SUCCESS (rc))
702 {
703 *ppInstance = &gCtx;
704 }
705 else
706 {
707 vboxClipboardDisconnect (&gCtx);
708 }
709
710 return rc;
711}
712
713unsigned __stdcall VBoxClipboardThread (void *pInstance)
714{
715 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
716
717 dprintf(("VBoxClipboardThread\n"));
718
719 HANDLE hHostEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
720
721 /* The thread waits for incoming data from the host.
722 * Register an event notification.
723 */
724 for (;;)
725 {
726 uint32_t u32Format;
727 uint32_t u32Size;
728
729 VBoxClipboardHostEventQuery parms;
730
731 VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_QUERY);
732
733 VBoxHGCMParmUInt32Set (&parms.format, 0);
734 VBoxHGCMParmUInt32Set (&parms.size, 0);
735
736 DWORD cbReturned;
737
738 if (!DeviceIoControl (pCtx->pEnv->hDriver,
739 IOCTL_VBOXGUEST_HGCM_CALL,
740 &parms, sizeof (parms),
741 &parms, sizeof (parms),
742 &cbReturned,
743 NULL))
744 {
745 dprintf(("Failed to call the driver for host event\n"));
746
747 /* Wait a bit before retrying. */
748 if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
749 {
750 break;
751 }
752
753 continue;
754 }
755
756 int rc = parms.hdr.result;
757
758 if (VBOX_SUCCESS (rc))
759 {
760 rc = VBoxHGCMParmUInt32Get (&parms.format, &u32Format);
761
762 if (VBOX_SUCCESS (rc))
763 {
764 rc = VBoxHGCMParmUInt32Get (&parms.size, &u32Size);
765
766 if (VBOX_SUCCESS (rc))
767 {
768 vboxClipboardHostEvent (pCtx, u32Format, u32Size);
769 }
770 }
771 }
772
773 dprintf(("processed host event rc = %d\n", rc));
774 }
775
776 return 0;
777}
778
779void VBoxClipboardDestroy (const VBOXSERVICEENV *pEnv, void *pInstance)
780{
781 VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
782
783 if (pCtx != &gCtx)
784 {
785 dprintf(("VBoxClipboardDestroy: invalid instance %p (our %p)!!!\n", pCtx, &gCtx));
786
787 pCtx = &gCtx;
788 }
789
790 vboxClipboardDestroy (pCtx);
791
792 vboxClipboardDisconnect (pCtx);
793
794 memset (pCtx, 0, sizeof (*pCtx));
795
796 return;
797}
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