VirtualBox

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

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

Export HostServices

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.8 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 as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
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 bool fMessageReturned = vboxSvcClipboardReturnMsg (pClient, pClient->async.paParms);
200
201 if (fMessageReturned)
202 {
203 LogFlow(("vboxSvcClipboardReportMsg: CallComplete\n"));
204 g_pHelpers->pfnCallComplete (pClient->async.callHandle, VINF_SUCCESS);
205 pClient->fAsync = false;
206 }
207 }
208
209 vboxSvcClipboardUnlock ();
210 }
211}
212
213static int svcInit (void)
214{
215 RTCritSectInit (&critsect);
216 vboxSvcClipboardModeSet (VBOX_SHARED_CLIPBOARD_MODE_OFF);
217 return vboxClipboardInit ();
218}
219
220static DECLCALLBACK(int) svcUnload (void)
221{
222 vboxClipboardDestroy ();
223 RTCritSectDelete (&critsect);
224 return VINF_SUCCESS;
225}
226
227static DECLCALLBACK(int) svcConnect (uint32_t u32ClientID, void *pvClient)
228{
229 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
230
231 /* Register the client. */
232 int rc = VINF_SUCCESS;
233
234 memset (pClient, 0, sizeof (*pClient));
235
236 pClient->u32ClientID = u32ClientID;
237
238 rc = vboxClipboardConnect (pClient);
239
240 if (VBOX_SUCCESS (rc))
241 {
242 g_pClient = pClient;
243 }
244
245 Log(("vboxClipboardConnect: rc = %Vrc\n", rc));
246
247 return rc;
248}
249
250static DECLCALLBACK(int) svcDisconnect (uint32_t u32ClientID, void *pvClient)
251{
252 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
253
254 vboxSvcClipboardReportMsg (pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT, 0);
255
256 vboxClipboardDisconnect (pClient);
257
258 memset (pClient, 0, sizeof (*pClient));
259
260 g_pClient = NULL;
261
262 return VINF_SUCCESS;
263}
264
265static DECLCALLBACK(void) svcCall (VBOXHGCMCALLHANDLE callHandle,
266 uint32_t u32ClientID,
267 void *pvClient,
268 uint32_t u32Function,
269 uint32_t cParms,
270 VBOXHGCMSVCPARM paParms[])
271{
272 int rc = VINF_SUCCESS;
273
274 Log(("svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",
275 u32ClientID, u32Function, cParms, paParms));
276
277 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
278
279 bool fAsynchronousProcessing = false;
280
281#ifdef DEBUG
282 uint32_t i;
283
284 for (i = 0; i < cParms; i++)
285 {
286 /** @todo parameters other than 32 bit */
287 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
288 }
289#endif
290
291 switch (u32Function)
292 {
293 case VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG:
294 {
295 /* The quest requests a host message. */
296 Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG\n"));
297
298 if (cParms != VBOX_HGCM_PARM_COUNT (VBoxClipboardGetHostMsg))
299 {
300 rc = VERR_INVALID_PARAMETER;
301 }
302 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* msg */
303 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* formats */
304 )
305 {
306 rc = VERR_INVALID_PARAMETER;
307 }
308 else
309 {
310 /* Atomically verify the client's state. */
311 if (vboxSvcClipboardLock ())
312 {
313 bool fMessageReturned = vboxSvcClipboardReturnMsg (pClient, paParms);
314
315 if (fMessageReturned)
316 {
317 /* Just return to the caller. */
318 pClient->fAsync = false;
319 }
320 else
321 {
322 /* No event available at the time. Process asynchronously. */
323 fAsynchronousProcessing = true;
324
325 pClient->fAsync = true;
326 pClient->async.callHandle = callHandle;
327 pClient->async.paParms = paParms;
328
329 Log(("svcCall: async.\n"));
330 }
331
332 vboxSvcClipboardUnlock ();
333 }
334 else
335 {
336 rc = VERR_NOT_SUPPORTED;
337 }
338 }
339 } break;
340
341 case VBOX_SHARED_CLIPBOARD_FN_FORMATS:
342 {
343 /* The guest reports that some formats are available. */
344 Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_FORMATS\n"));
345
346 if (cParms != VBOX_HGCM_PARM_COUNT (VBoxClipboardFormats))
347 {
348 rc = VERR_INVALID_PARAMETER;
349 }
350 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* formats */
351 )
352 {
353 rc = VERR_INVALID_PARAMETER;
354 }
355 else
356 {
357 uint32_t u32Formats;
358
359 rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Formats);
360
361 if (VBOX_SUCCESS (rc))
362 {
363 if ( vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
364 && vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
365 {
366 rc = VERR_NOT_SUPPORTED;
367 break;
368 }
369
370 if (g_pfnExtension)
371 {
372 VBOXCLIPBOARDEXTPARMS parms;
373
374 parms.u32Format = u32Formats;
375
376 g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof (parms));
377 }
378 else
379 {
380 vboxClipboardFormatAnnounce (pClient, u32Formats);
381 }
382 }
383 }
384 } break;
385
386 case VBOX_SHARED_CLIPBOARD_FN_READ_DATA:
387 {
388 /* The guest wants to read data in the given format. */
389 Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_READ_DATA\n"));
390
391 if (cParms != VBOX_HGCM_PARM_COUNT (VBoxClipboardReadData))
392 {
393 rc = VERR_INVALID_PARAMETER;
394 }
395 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* format */
396 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* ptr */
397 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* size */
398 )
399 {
400 rc = VERR_INVALID_PARAMETER;
401 }
402 else
403 {
404 uint32_t u32Format;
405 void *pv;
406 uint32_t cb;
407
408 rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Format);
409
410 if (VBOX_SUCCESS (rc))
411 {
412 rc = VBoxHGCMParmPtrGet (&paParms[1], &pv, &cb);
413
414 if (VBOX_SUCCESS (rc))
415 {
416 if ( vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
417 && vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
418 {
419 rc = VERR_NOT_SUPPORTED;
420 break;
421 }
422
423 uint32_t cbActual = 0;
424
425 if (g_pfnExtension)
426 {
427 VBOXCLIPBOARDEXTPARMS parms;
428
429 parms.u32Format = u32Format;
430 parms.pvData = pv;
431 parms.cbData = cb;
432
433 rc = g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_READ, &parms, sizeof (parms));
434
435 if (VBOX_SUCCESS (rc))
436 {
437 cbActual = parms.cbData;
438 }
439 }
440 else
441 {
442 rc = vboxClipboardReadData (pClient, u32Format, pv, cb, &cbActual);
443 }
444
445 if (VBOX_SUCCESS (rc))
446 {
447 VBoxHGCMParmUInt32Set (&paParms[2], cbActual);
448 }
449 }
450 }
451 }
452 } break;
453
454 case VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA:
455 {
456 /* The guest writes the requested data. */
457 Log(("svcCall: VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA\n"));
458
459 if (cParms != VBOX_HGCM_PARM_COUNT (VBoxClipboardWriteData))
460 {
461 rc = VERR_INVALID_PARAMETER;
462 }
463 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* format */
464 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* ptr */
465 )
466 {
467 rc = VERR_INVALID_PARAMETER;
468 }
469 else
470 {
471 void *pv;
472 uint32_t cb;
473 uint32_t u32Format;
474
475 rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Format);
476
477 if (VBOX_SUCCESS (rc))
478 {
479 rc = VBoxHGCMParmPtrGet (&paParms[1], &pv, &cb);
480
481 if (VBOX_SUCCESS (rc))
482 {
483 if ( vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
484 && vboxSvcClipboardMode () != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
485 {
486 rc = VERR_NOT_SUPPORTED;
487 break;
488 }
489
490 if (g_pfnExtension)
491 {
492 VBOXCLIPBOARDEXTPARMS parms;
493
494 parms.u32Format = u32Format;
495 parms.pvData = pv;
496 parms.cbData = cb;
497
498 g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_DATA_WRITE, &parms, sizeof (parms));
499 }
500 else
501 {
502 vboxClipboardWriteData (pClient, pv, cb, u32Format);
503 }
504 }
505 }
506 }
507 } break;
508
509 default:
510 {
511 rc = VERR_NOT_IMPLEMENTED;
512 }
513 }
514
515 LogFlow(("svcCall: rc = %Vrc\n", rc));
516
517 if (!fAsynchronousProcessing)
518 {
519 g_pHelpers->pfnCallComplete (callHandle, rc);
520 }
521}
522
523/*
524 * We differentiate between a function handler for the guest and one for the host.
525 */
526static DECLCALLBACK(int) svcHostCall (uint32_t u32Function,
527 uint32_t cParms,
528 VBOXHGCMSVCPARM paParms[])
529{
530 int rc = VINF_SUCCESS;
531
532 Log(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n",
533 u32Function, cParms, paParms));
534
535 switch (u32Function)
536 {
537 case VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE:
538 {
539 Log(("svcCall: VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE\n"));
540
541 if (cParms != 1)
542 {
543 rc = VERR_INVALID_PARAMETER;
544 }
545 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* mode */
546 )
547 {
548 rc = VERR_INVALID_PARAMETER;
549 }
550 else
551 {
552 uint32_t u32Mode = VBOX_SHARED_CLIPBOARD_MODE_OFF;
553
554 rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Mode);
555
556 /* The setter takes care of invalid values. */
557 vboxSvcClipboardModeSet (u32Mode);
558 }
559 } break;
560
561 default:
562 break;
563 }
564
565 LogFlow(("svcHostCall: rc = %Vrc\n", rc));
566 return rc;
567}
568
569static DECLCALLBACK(int) svcSaveState(uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
570{
571 /* If there are any pending requests, they must be completed here. Since
572 * the service is single threaded, there could be only requests
573 * which the service itself has postponed.
574 *
575 * HGCM knows that the state is being saved and that the pfnComplete
576 * calls are just clean ups. These requests are saved by the VMMDev.
577 *
578 * When the state will be restored, these requests will be reissued
579 * by VMMDev. The service therefore must save state as if there were no
580 * pending request.
581 */
582 Log(("svcSaveState: u32ClientID = %d\n", u32ClientID));
583
584 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
585
586 /* Save client structure length & contents */
587 int rc = SSMR3PutU32(pSSM, sizeof(*pClient));
588 AssertRCReturn(rc, rc);
589
590 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
591 AssertRCReturn(rc, rc);
592
593 if (pClient->fAsync)
594 {
595 g_pHelpers->pfnCallComplete (pClient->async.callHandle, VINF_SUCCESS /* error code is not important here. */);
596 pClient->fAsync = false;
597 }
598
599 return VINF_SUCCESS;
600}
601
602static DECLCALLBACK(int) svcLoadState(uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
603{
604 Log(("svcLoadState: u32ClientID = %d\n", u32ClientID));
605
606 VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;
607
608 /* Existing client can not be in async state yet. */
609 Assert(!pClient->fAsync);
610
611 /* Restore the client data. */
612 uint32_t len;
613 int rc = SSMR3GetU32(pSSM, &len);
614 AssertRCReturn(rc, rc);
615
616 if (len != sizeof(VBOXCLIPBOARDCLIENTDATA))
617 {
618 Log(("Client len mismatch: %d %d\n", len, sizeof (VBOXCLIPBOARDCLIENTDATA)));
619 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
620 }
621
622 VBOXCLIPBOARDCLIENTDATA client;
623 rc = SSMR3GetMem(pSSM, &client, sizeof(client));
624 AssertRCReturn(rc, rc);
625
626 /* Verify the loaded clients data and update the pClient. */
627 if (pClient->u32ClientID != client.u32ClientID)
628 {
629 Log(("Client ID mismatch: %d %d\n", pClient->u32ClientID, client.u32ClientID));
630 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
631 }
632
633 pClient->fMsgQuit = client.fMsgQuit;
634 pClient->fMsgReadData = client.fMsgReadData;
635 pClient->fMsgFormats = client.fMsgFormats;
636 pClient->u32RequestedFormat = client.u32RequestedFormat;
637
638 /* Actual host data are to be reported to guest (SYNC). */
639 vboxClipboardSync (pClient);
640
641 return VINF_SUCCESS;
642}
643
644static DECLCALLBACK(int) extCallback (uint32_t u32Function, uint32_t u32Format, void *pvData, uint32_t cbData)
645{
646 if (g_pClient != NULL)
647 {
648 switch (u32Function)
649 {
650 case VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE:
651 {
652 vboxSvcClipboardReportMsg (g_pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, u32Format);
653 } break;
654
655 case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
656 {
657 vboxSvcClipboardReportMsg (g_pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, u32Format);
658 } break;
659
660 default:
661 return VERR_NOT_SUPPORTED;
662 }
663 }
664
665 return VINF_SUCCESS;
666}
667
668static DECLCALLBACK(int) svcRegisterExtension(PFNHGCMSVCEXT pfnExtension, void *pvExtension)
669{
670 LogFlowFunc(("pfnExtension = %p\n", pfnExtension));
671
672 VBOXCLIPBOARDEXTPARMS parms;
673
674 if (pfnExtension)
675 {
676 /* Install extension. */
677 g_pfnExtension = pfnExtension;
678 g_pvExtension = pvExtension;
679
680 parms.pvData = (void *)extCallback;
681 g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK, &parms, sizeof (parms));
682 }
683 else
684 {
685 if (g_pfnExtension)
686 {
687 parms.pvData = NULL;
688 g_pfnExtension (g_pvExtension, VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK, &parms, sizeof (parms));
689 }
690
691 /* Uninstall extension. */
692 g_pfnExtension = NULL;
693 g_pvExtension = NULL;
694 }
695
696 return VINF_SUCCESS;
697}
698
699extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
700{
701 int rc = VINF_SUCCESS;
702
703 LogFlowFunc(("ptable = %p\n", ptable));
704
705 if (!ptable)
706 {
707 rc = VERR_INVALID_PARAMETER;
708 }
709 else
710 {
711 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
712
713 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
714 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
715 {
716 rc = VERR_INVALID_PARAMETER;
717 }
718 else
719 {
720 g_pHelpers = ptable->pHelpers;
721
722 ptable->cbClient = sizeof (VBOXCLIPBOARDCLIENTDATA);
723
724 ptable->pfnUnload = svcUnload;
725 ptable->pfnConnect = svcConnect;
726 ptable->pfnDisconnect = svcDisconnect;
727 ptable->pfnCall = svcCall;
728 ptable->pfnHostCall = svcHostCall;
729 ptable->pfnSaveState = svcSaveState;
730 ptable->pfnLoadState = svcLoadState;
731 ptable->pfnRegisterExtension = svcRegisterExtension;
732
733 /* Service specific initialization. */
734 rc = svcInit ();
735 }
736 }
737
738 return rc;
739}
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