VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/service.cpp@ 9125

Last change on this file since 9125 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.1 KB
Line 
1/** @file
2 *
3 * Shared Clipboard:
4 * Host service entry points.
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 <VBox/HostServices/VBoxClipboardSvc.h>
24#include <VBox/HostServices/VBoxClipboardExt.h>
25
26#include <iprt/alloc.h>
27#include <iprt/string.h>
28#include <iprt/assert.h>
29#include <iprt/critsect.h>
30#include <VBox/ssm.h>
31
32#include "VBoxClipboard.h"
33
34#define VBOX_HGCM_PARM_COUNT(a) ((sizeof (a) - sizeof (((a *)0)->hdr)) / sizeof (HGCMFunctionParameter))
35
36static void VBoxHGCMParmUInt32Set (VBOXHGCMSVCPARM *pParm, uint32_t u32)
37{
38 pParm->type = VBOX_HGCM_SVC_PARM_32BIT;
39 pParm->u.uint32 = u32;
40}
41
42static int VBoxHGCMParmUInt32Get (VBOXHGCMSVCPARM *pParm, uint32_t *pu32)
43{
44 if (pParm->type == VBOX_HGCM_SVC_PARM_32BIT)
45 {
46 *pu32 = pParm->u.uint32;
47 return VINF_SUCCESS;
48 }
49
50 return VERR_INVALID_PARAMETER;
51}
52
53#if 0
54static void VBoxHGCMParmPtrSet (VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)
55{
56 pParm->type = VBOX_HGCM_SVC_PARM_PTR;
57 pParm->u.pointer.size = cb;
58 pParm->u.pointer.addr = pv;
59}
60#endif
61
62static int VBoxHGCMParmPtrGet (VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
63{
64 if (pParm->type == VBOX_HGCM_SVC_PARM_PTR)
65 {
66 *ppv = pParm->u.pointer.addr;
67 *pcb = pParm->u.pointer.size;
68 return VINF_SUCCESS;
69 }
70
71 return VERR_INVALID_PARAMETER;
72}
73
74static PVBOXHGCMSVCHELPERS g_pHelpers;
75
76static RTCRITSECT critsect;
77static uint32_t g_u32Mode;
78
79static PFNHGCMSVCEXT g_pfnExtension;
80static void *g_pvExtension;
81
82static VBOXCLIPBOARDCLIENTDATA *g_pClient;
83
84static uint32_t vboxSvcClipboardMode (void)
85{
86 return g_u32Mode;
87}
88
89static void vboxSvcClipboardModeSet (uint32_t u32Mode)
90{
91 switch (u32Mode)
92 {
93 case VBOX_SHARED_CLIPBOARD_MODE_OFF:
94 case VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST:
95 case VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST:
96 case VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL:
97 g_u32Mode = u32Mode;
98 break;
99
100 default:
101 g_u32Mode = VBOX_SHARED_CLIPBOARD_MODE_OFF;
102 }
103}
104
105bool vboxSvcClipboardLock (void)
106{
107 return VBOX_SUCCESS(RTCritSectEnter (&critsect));
108}
109
110void vboxSvcClipboardUnlock (void)
111{
112 RTCritSectLeave (&critsect);
113}
114
115/* Set the HGCM parameters according to pending messages.
116 * Executed under the clipboard lock.
117 */
118static bool vboxSvcClipboardReturnMsg (VBOXCLIPBOARDCLIENTDATA *pClient, VBOXHGCMSVCPARM paParms[])
119{
120 /* Message priority is taken into account. */
121 if (pClient->fMsgQuit)
122 {
123 LogFlow(("vboxSvcClipboardReturnMsg: Quit\n"));
124 VBoxHGCMParmUInt32Set (&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
125 VBoxHGCMParmUInt32Set (&paParms[1], 0);
126 pClient->fMsgQuit = false;
127 }
128 else if (pClient->fMsgReadData)
129 {
130 LogFlow(("vboxSvcClipboardReturnMsg: ReadData %02X\n", pClient->u32RequestedFormat));
131 VBoxHGCMParmUInt32Set (&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
132 VBoxHGCMParmUInt32Set (&paParms[1], pClient->u32RequestedFormat);
133 pClient->fMsgReadData = false;
134 }
135 else if (pClient->fMsgFormats)
136 {
137 LogFlow(("vboxSvcClipboardReturnMsg: Formats %02X\n", pClient->u32AvailableFormats));
138 VBoxHGCMParmUInt32Set (&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS);
139 VBoxHGCMParmUInt32Set (&paParms[1], pClient->u32AvailableFormats);
140 pClient->fMsgFormats = false;
141 }
142 else
143 {
144 /* No pending messages. */
145 LogFlow(("vboxSvcClipboardReturnMsg: no message\n"));
146 return false;
147 }
148
149 /* Message information assigned. */
150 return true;
151}
152
153void vboxSvcClipboardReportMsg (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats)
154{
155 if (vboxSvcClipboardLock ())
156 {
157 switch (u32Msg)
158 {
159 case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
160 {
161 LogFlow(("vboxSvcClipboardReportMsg: Quit\n"));
162 pClient->fMsgQuit = true;
163 } break;
164 case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
165 {
166 if ( vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
167 && vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
168 {
169 /* Skip the message. */
170 break;
171 }
172
173 LogFlow(("vboxSvcClipboardReportMsg: ReadData %02X\n", u32Formats));
174 pClient->u32RequestedFormat = u32Formats;
175 pClient->fMsgReadData = true;
176 } break;
177 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
178 {
179 if ( vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
180 && vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
181 {
182 /* Skip the message. */
183 break;
184 }
185
186 LogFlow(("vboxSvcClipboardReportMsg: Formats %02X\n", u32Formats));
187 pClient->u32AvailableFormats = u32Formats;
188 pClient->fMsgFormats = true;
189 } break;
190 default:
191 {
192 /* Invalid message. */
193 LogFlow(("vboxSvcClipboardReportMsg: invalid message %d\n", u32Msg));
194 } break;
195 }
196
197 if (pClient->fAsync)
198 {
199 /* The client waits for a responce. */
200 bool fMessageReturned = vboxSvcClipboardReturnMsg (pClient, pClient->async.paParms);
201
202 /* Make a copy of the handle. */
203 VBOXHGCMCALLHANDLE callHandle = pClient->async.callHandle;
204
205 if (fMessageReturned)
206 {
207 /* There is a responce. */
208 pClient->fAsync = false;
209 }
210
211 vboxSvcClipboardUnlock ();
212
213 if (fMessageReturned)
214 {
215 LogFlow(("vboxSvcClipboardReportMsg: CallComplete\n"));
216 g_pHelpers->pfnCallComplete (callHandle, VINF_SUCCESS);
217 }
218 }
219 else
220 {
221 vboxSvcClipboardUnlock ();
222 }
223 }
224}
225
226static int svcInit (void)
227{
228 int rc = RTCritSectInit (&critsect);
229
230 if (RT_SUCCESS (rc))
231 {
232 vboxSvcClipboardModeSet (VBOX_SHARED_CLIPBOARD_MODE_OFF);
233
234 rc = vboxClipboardInit ();
235
236 /* Clean up on failure, because 'svnUnload' will not be called
237 * if the 'svcInit' returns an error.
238 */
239 if (VBOX_FAILURE (rc))
240 {
241 RTCritSectDelete (&critsect);
242 }
243 }
244
245 return rc;
246}
247
248static DECLCALLBACK(int) svcUnload (void *)
249{
250 vboxClipboardDestroy ();
251 RTCritSectDelete (&critsect);
252 return VINF_SUCCESS;
253}
254
255/**
256 * Disconnect the host side of the shared clipboard and send a "host disconnected" message
257 * to the guest side.
258 */
259static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
260{
261 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
262
263 vboxSvcClipboardReportMsg (pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT, 0);
264
265 vboxClipboardDisconnect (pClient);
266
267 memset (pClient, 0, sizeof (*pClient));
268
269 g_pClient = NULL;
270
271 return VINF_SUCCESS;
272}
273
274static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
275{
276 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
277
278 int rc = VINF_SUCCESS;
279
280 /* If there is already a client connected then we want to release it first. */
281 if (g_pClient != NULL)
282 {
283 uint32_t u32ClientID = g_pClient->u32ClientID;
284
285 svcDisconnect(NULL, u32ClientID, g_pClient);
286 /* And free the resources in the hgcm subsystem. */
287 g_pHelpers->pfnDisconnectClient(g_pHelpers->pvInstance, u32ClientID);
288 }
289
290 /* Register the client. */
291 memset (pClient, 0, sizeof (*pClient));
292
293 pClient->u32ClientID = u32ClientID;
294
295 rc = vboxClipboardConnect (pClient);
296
297 if (VBOX_SUCCESS (rc))
298 {
299 g_pClient = pClient;
300 }
301
302 Log(("vboxClipboardConnect: rc = %Vrc\n", rc));
303
304 return rc;
305}
306
307static DECLCALLBACK(void) svcCall (void *,
308 VBOXHGCMCALLHANDLE callHandle,
309 uint32_t u32ClientID,
310 void *pvClient,
311 uint32_t u32Function,
312 uint32_t cParms,
313 VBOXHGCMSVCPARM paParms[])
314{
315 int rc = VINF_SUCCESS;
316
317 Log(("svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",
318 u32ClientID, u32Function, cParms, paParms));
319
320 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
321
322 bool fAsynchronousProcessing = false;
323
324#ifdef DEBUG
325 uint32_t i;
326
327 for (i = 0; i < cParms; i++)
328 {
329 /** @todo parameters other than 32 bit */
330 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
331 }
332#endif
333
334 switch (u32Function)
335 {
336 case VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG:
337 {
338 /* The quest requests a host message. */
339 Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG\n"));
340
341 if (cParms != VBOX_HGCM_PARM_COUNT (VBoxClipboardGetHostMsg))
342 {
343 rc = VERR_INVALID_PARAMETER;
344 }
345 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* msg */
346 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* formats */
347 )
348 {
349 rc = VERR_INVALID_PARAMETER;
350 }
351 else
352 {
353 /* Atomically verify the client's state. */
354 if (vboxSvcClipboardLock ())
355 {
356 bool fMessageReturned = vboxSvcClipboardReturnMsg (pClient, paParms);
357
358 if (fMessageReturned)
359 {
360 /* Just return to the caller. */
361 pClient->fAsync = false;
362 }
363 else
364 {
365 /* No event available at the time. Process asynchronously. */
366 fAsynchronousProcessing = true;
367
368 pClient->fAsync = true;
369 pClient->async.callHandle = callHandle;
370 pClient->async.paParms = paParms;
371
372 Log(("svcCall: async.\n"));
373 }
374
375 vboxSvcClipboardUnlock ();
376 }
377 else
378 {
379 rc = VERR_NOT_SUPPORTED;
380 }
381 }
382 } break;
383
384 case VBOX_SHARED_CLIPBOARD_FN_FORMATS:
385 {
386 /* The guest reports that some formats are available. */
387 Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_FORMATS\n"));
388
389 if (cParms != VBOX_HGCM_PARM_COUNT (VBoxClipboardFormats))
390 {
391 rc = VERR_INVALID_PARAMETER;
392 }
393 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* formats */
394 )
395 {
396 rc = VERR_INVALID_PARAMETER;
397 }
398 else
399 {
400 uint32_t u32Formats;
401
402 rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Formats);
403
404 if (VBOX_SUCCESS (rc))
405 {
406 if ( vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
407 && vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
408 {
409 rc = VERR_NOT_SUPPORTED;
410 break;
411 }
412
413 if (g_pfnExtension)
414 {
415 VBOXCLIPBOARDEXTPARMS parms;
416
417 parms.u32Format = u32Formats;
418
419 g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof (parms));
420 }
421 else
422 {
423 vboxClipboardFormatAnnounce (pClient, u32Formats);
424 }
425 }
426 }
427 } break;
428
429 case VBOX_SHARED_CLIPBOARD_FN_READ_DATA:
430 {
431 /* The guest wants to read data in the given format. */
432 Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_READ_DATA\n"));
433
434 if (cParms != VBOX_HGCM_PARM_COUNT (VBoxClipboardReadData))
435 {
436 rc = VERR_INVALID_PARAMETER;
437 }
438 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* format */
439 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* ptr */
440 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* size */
441 )
442 {
443 rc = VERR_INVALID_PARAMETER;
444 }
445 else
446 {
447 uint32_t u32Format;
448 void *pv;
449 uint32_t cb;
450
451 rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Format);
452
453 if (VBOX_SUCCESS (rc))
454 {
455 rc = VBoxHGCMParmPtrGet (&paParms[1], &pv, &cb);
456
457 if (VBOX_SUCCESS (rc))
458 {
459 if ( vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
460 && vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
461 {
462 rc = VERR_NOT_SUPPORTED;
463 break;
464 }
465
466 uint32_t cbActual = 0;
467
468 if (g_pfnExtension)
469 {
470 VBOXCLIPBOARDEXTPARMS parms;
471
472 parms.u32Format = u32Format;
473 parms.pvData = pv;
474 parms.cbData = cb;
475
476 rc = g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_READ, &parms, sizeof (parms));
477
478 if (VBOX_SUCCESS (rc))
479 {
480 cbActual = parms.cbData;
481 }
482 }
483 else
484 {
485 rc = vboxClipboardReadData (pClient, u32Format, pv, cb, &cbActual);
486 }
487
488 if (VBOX_SUCCESS (rc))
489 {
490 VBoxHGCMParmUInt32Set (&paParms[2], cbActual);
491 }
492 }
493 }
494 }
495 } break;
496
497 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA:
498 {
499 /* The guest writes the requested data. */
500 Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA\n"));
501
502 if (cParms != VBOX_HGCM_PARM_COUNT (VBoxClipboardWriteData))
503 {
504 rc = VERR_INVALID_PARAMETER;
505 }
506 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* format */
507 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* ptr */
508 )
509 {
510 rc = VERR_INVALID_PARAMETER;
511 }
512 else
513 {
514 void *pv;
515 uint32_t cb;
516 uint32_t u32Format;
517
518 rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Format);
519
520 if (VBOX_SUCCESS (rc))
521 {
522 rc = VBoxHGCMParmPtrGet (&paParms[1], &pv, &cb);
523
524 if (VBOX_SUCCESS (rc))
525 {
526 if ( vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
527 && vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
528 {
529 rc = VERR_NOT_SUPPORTED;
530 break;
531 }
532
533 if (g_pfnExtension)
534 {
535 VBOXCLIPBOARDEXTPARMS parms;
536
537 parms.u32Format = u32Format;
538 parms.pvData = pv;
539 parms.cbData = cb;
540
541 g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_WRITE, &parms, sizeof (parms));
542 }
543 else
544 {
545 vboxClipboardWriteData (pClient, pv, cb, u32Format);
546 }
547 }
548 }
549 }
550 } break;
551
552 default:
553 {
554 rc = VERR_NOT_IMPLEMENTED;
555 }
556 }
557
558 LogFlow(("svcCall: rc = %Vrc\n", rc));
559
560 if (!fAsynchronousProcessing)
561 {
562 g_pHelpers->pfnCallComplete (callHandle, rc);
563 }
564}
565
566/*
567 * We differentiate between a function handler for the guest and one for the host.
568 */
569static DECLCALLBACK(int) svcHostCall (void *,
570 uint32_t u32Function,
571 uint32_t cParms,
572 VBOXHGCMSVCPARM paParms[])
573{
574 int rc = VINF_SUCCESS;
575
576 Log(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n",
577 u32Function, cParms, paParms));
578
579 switch (u32Function)
580 {
581 case VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE:
582 {
583 Log(("svcCall: VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE\n"));
584
585 if (cParms != 1)
586 {
587 rc = VERR_INVALID_PARAMETER;
588 }
589 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* mode */
590 )
591 {
592 rc = VERR_INVALID_PARAMETER;
593 }
594 else
595 {
596 uint32_t u32Mode = VBOX_SHARED_CLIPBOARD_MODE_OFF;
597
598 rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Mode);
599
600 /* The setter takes care of invalid values. */
601 vboxSvcClipboardModeSet (u32Mode);
602 }
603 } break;
604
605 default:
606 break;
607 }
608
609 LogFlow(("svcHostCall: rc = %Vrc\n", rc));
610 return rc;
611}
612
613static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
614{
615 /* If there are any pending requests, they must be completed here. Since
616 * the service is single threaded, there could be only requests
617 * which the service itself has postponed.
618 *
619 * HGCM knows that the state is being saved and that the pfnComplete
620 * calls are just clean ups. These requests are saved by the VMMDev.
621 *
622 * When the state will be restored, these requests will be reissued
623 * by VMMDev. The service therefore must save state as if there were no
624 * pending request.
625 */
626 Log(("svcSaveState: u32ClientID = %d\n", u32ClientID));
627
628 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
629
630 /* Save client structure length & contents */
631 int rc = SSMR3PutU32(pSSM, sizeof(*pClient));
632 AssertRCReturn(rc, rc);
633
634 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
635 AssertRCReturn(rc, rc);
636
637 if (pClient->fAsync)
638 {
639 g_pHelpers->pfnCallComplete (pClient->async.callHandle, VINF_SUCCESS /* error code is not important here. */);
640 pClient->fAsync = false;
641 }
642
643 return VINF_SUCCESS;
644}
645
646static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
647{
648 Log(("svcLoadState: u32ClientID = %d\n", u32ClientID));
649
650 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
651
652 /* Existing client can not be in async state yet. */
653 Assert(!pClient->fAsync);
654
655 /* Restore the client data. */
656 uint32_t len;
657 int rc = SSMR3GetU32(pSSM, &len);
658 AssertRCReturn(rc, rc);
659
660 if (len != sizeof(VBOXCLIPBOARDCLIENTDATA))
661 {
662 Log(("Client len mismatch: %d %d\n", len, sizeof (VBOXCLIPBOARDCLIENTDATA)));
663 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
664 }
665
666 VBOXCLIPBOARDCLIENTDATA client;
667 rc = SSMR3GetMem(pSSM, &client, sizeof(client));
668 AssertRCReturn(rc, rc);
669
670 /* Verify the loaded clients data and update the pClient. */
671 if (pClient->u32ClientID != client.u32ClientID)
672 {
673 Log(("Client ID mismatch: %d %d\n", pClient->u32ClientID, client.u32ClientID));
674 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
675 }
676
677 pClient->fMsgQuit = client.fMsgQuit;
678 pClient->fMsgReadData = client.fMsgReadData;
679 pClient->fMsgFormats = client.fMsgFormats;
680 pClient->u32RequestedFormat = client.u32RequestedFormat;
681
682 /* Actual host data are to be reported to guest (SYNC). */
683 vboxClipboardSync (pClient);
684
685 return VINF_SUCCESS;
686}
687
688static DECLCALLBACK(int) extCallback (uint32_t u32Function, uint32_t u32Format, void *pvData, uint32_t cbData)
689{
690 if (g_pClient != NULL)
691 {
692 switch (u32Function)
693 {
694 case VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE:
695 {
696 vboxSvcClipboardReportMsg (g_pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, u32Format);
697 } break;
698
699 case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
700 {
701 vboxSvcClipboardReportMsg (g_pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, u32Format);
702 } break;
703
704 default:
705 return VERR_NOT_SUPPORTED;
706 }
707 }
708
709 return VINF_SUCCESS;
710}
711
712static DECLCALLBACK(int) svcRegisterExtension(void *, PFNHGCMSVCEXT pfnExtension, void *pvExtension)
713{
714 LogFlowFunc(("pfnExtension = %p\n", pfnExtension));
715
716 VBOXCLIPBOARDEXTPARMS parms;
717
718 if (pfnExtension)
719 {
720 /* Install extension. */
721 g_pfnExtension = pfnExtension;
722 g_pvExtension = pvExtension;
723
724 parms.pvData = (void *)extCallback;
725 g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK, &parms, sizeof (parms));
726 }
727 else
728 {
729 if (g_pfnExtension)
730 {
731 parms.pvData = NULL;
732 g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK, &parms, sizeof (parms));
733 }
734
735 /* Uninstall extension. */
736 g_pfnExtension = NULL;
737 g_pvExtension = NULL;
738 }
739
740 return VINF_SUCCESS;
741}
742
743extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
744{
745 int rc = VINF_SUCCESS;
746
747 LogFlowFunc(("ptable = %p\n", ptable));
748
749 if (!ptable)
750 {
751 rc = VERR_INVALID_PARAMETER;
752 }
753 else
754 {
755 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
756
757 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
758 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
759 {
760 rc = VERR_INVALID_PARAMETER;
761 }
762 else
763 {
764 g_pHelpers = ptable->pHelpers;
765
766 ptable->cbClient = sizeof (VBOXCLIPBOARDCLIENTDATA);
767
768 ptable->pfnUnload = svcUnload;
769 ptable->pfnConnect = svcConnect;
770 ptable->pfnDisconnect = svcDisconnect;
771 ptable->pfnCall = svcCall;
772 ptable->pfnHostCall = svcHostCall;
773 ptable->pfnSaveState = svcSaveState;
774 ptable->pfnLoadState = svcLoadState;
775 ptable->pfnRegisterExtension = svcRegisterExtension;
776 ptable->pvService = NULL;
777
778 /* Service specific initialization. */
779 rc = svcInit ();
780 }
781 }
782
783 return rc;
784}
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