VirtualBox

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

Last change on this file since 8083 was 7801, checked in by vboxsync, 16 years ago

HGCM: Add user data pointer to HGCM service function table

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