VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedFolders/service.cpp@ 30037

Last change on this file since 30037 was 28800, checked in by vboxsync, 14 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 45.8 KB
Line 
1/** @file
2 * Shared Folders: Host service entry points.
3 */
4
5/*
6 * Copyright (C) 2006-2007 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#include <VBox/shflsvc.h>
18
19
20#include "shfl.h"
21#include "mappings.h"
22#include "shflhandle.h"
23#include "vbsf.h"
24#include <iprt/alloc.h>
25#include <iprt/string.h>
26#include <iprt/assert.h>
27#include <VBox/ssm.h>
28#include <VBox/pdm.h>
29
30#define SHFL_SSM_VERSION 2
31
32
33/* Shared Folders Host Service.
34 *
35 * Shared Folders map a host file system to guest logical filesystem.
36 * A mapping represents 'host name'<->'guest name' translation and a root
37 * identifier to be used to access this mapping.
38 * Examples: "C:\WINNT"<->"F:", "C:\WINNT\System32"<->"/mnt/host/system32".
39 *
40 * Therefore, host name and guest name are strings interpreted
41 * only by host service and guest client respectively. Host name is
42 * passed to guest only for informational purpose. Guest may for example
43 * display the string or construct volume label out of the string.
44 *
45 * Root identifiers are unique for whole guest life,
46 * that is until next guest reset/fresh start.
47 * 32 bit value incremented for each new mapping is used.
48 *
49 * Mapping strings are taken from VM XML configuration on VM startup.
50 * The service DLL takes mappings during initialization. There is
51 * also API for changing mappings at runtime.
52 *
53 * Current mappings and root identifiers are saved when VM is saved.
54 *
55 * Guest may use any of these mappings. Full path information
56 * about an object on a mapping consists of the root indentifier and
57 * a full path of object.
58 *
59 * Guest IFS connects to the service and calls SHFL_FN_QUERY_MAP
60 * function which returns current mappings. For guest convenience,
61 * removed mappings also returned with REMOVED flag and new mappings
62 * are marked with NEW flag.
63 *
64 * To access host file system guest just forwards file system calls
65 * to the service, and specifies full paths or handles for objects.
66 *
67 *
68 */
69
70
71PVBOXHGCMSVCHELPERS g_pHelpers;
72static PPDMLED pStatusLed = NULL;
73
74static DECLCALLBACK(int) svcUnload (void *)
75{
76 int rc = VINF_SUCCESS;
77
78 Log(("svcUnload\n"));
79
80 return rc;
81}
82
83static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
84{
85 int rc = VINF_SUCCESS;
86
87 NOREF(u32ClientID);
88 NOREF(pvClient);
89
90 LogRel(("SharedFolders host service: connected, u32ClientID = %d\n", u32ClientID));
91
92 return rc;
93}
94
95static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
96{
97 int rc = VINF_SUCCESS;
98 SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
99
100 LogRel(("SharedFolders host service: disconnected, u32ClientID = %d\n", u32ClientID));
101
102 vbsfDisconnect(pClient);
103 return rc;
104}
105
106/** @note We only save as much state as required to access the shared folder again after restore.
107 * All I/O requests pending at the time of saving will never be completed or result in errors.
108 * (file handles no longer valid etc)
109 * This works as designed at the moment. A full state save would be difficult and not always possible
110 * as the contents of a shared folder might change in between save and restore.
111 */
112static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
113{
114 SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
115
116 LogRel(("SharedFolders host service: saving state, u32ClientID = %d\n", u32ClientID));
117
118 int rc = SSMR3PutU32(pSSM, SHFL_SSM_VERSION);
119 AssertRCReturn(rc, rc);
120
121 rc = SSMR3PutU32(pSSM, SHFL_MAX_MAPPINGS);
122 AssertRCReturn(rc, rc);
123
124 /* Save client structure length & contents */
125 rc = SSMR3PutU32(pSSM, sizeof(*pClient));
126 AssertRCReturn(rc, rc);
127
128 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
129 AssertRCReturn(rc, rc);
130
131 /* Save all the active mappings. */
132 for (int i=0;i<SHFL_MAX_MAPPINGS;i++)
133 {
134 /* Mapping are saved in the order of increasing root handle values. */
135 MAPPING *pFolderMapping = vbsfMappingGetByRoot(i);
136
137 rc = SSMR3PutU32(pSSM, pFolderMapping? pFolderMapping->cMappings: 0);
138 AssertRCReturn(rc, rc);
139
140 rc = SSMR3PutBool(pSSM, pFolderMapping? pFolderMapping->fValid: false);
141 AssertRCReturn(rc, rc);
142
143 if (pFolderMapping && pFolderMapping->fValid)
144 {
145 uint32_t len;
146
147 len = ShflStringSizeOfBuffer(pFolderMapping->pFolderName);
148 rc = SSMR3PutU32(pSSM, len);
149 AssertRCReturn(rc, rc);
150
151 rc = SSMR3PutMem(pSSM, pFolderMapping->pFolderName, len);
152 AssertRCReturn(rc, rc);
153
154 len = ShflStringSizeOfBuffer(pFolderMapping->pMapName);
155 rc = SSMR3PutU32(pSSM, len);
156 AssertRCReturn(rc, rc);
157
158 rc = SSMR3PutMem(pSSM, pFolderMapping->pMapName, len);
159 AssertRCReturn(rc, rc);
160
161 rc = SSMR3PutBool(pSSM, pFolderMapping->fHostCaseSensitive);
162 AssertRCReturn(rc, rc);
163
164 rc = SSMR3PutBool(pSSM, pFolderMapping->fGuestCaseSensitive);
165 AssertRCReturn(rc, rc);
166 }
167 }
168
169 return VINF_SUCCESS;
170}
171
172static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
173{
174 uint32_t nrMappings;
175 SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
176 uint32_t len, version;
177
178 LogRel(("SharedFolders host service: loading state, u32ClientID = %d\n", u32ClientID));
179
180 int rc = SSMR3GetU32(pSSM, &version);
181 AssertRCReturn(rc, rc);
182
183 if (version != SHFL_SSM_VERSION)
184 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
185
186 rc = SSMR3GetU32(pSSM, &nrMappings);
187 AssertRCReturn(rc, rc);
188 if (nrMappings != SHFL_MAX_MAPPINGS)
189 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
190
191 /* Restore the client data (flags + path delimiter at the moment) */
192 rc = SSMR3GetU32(pSSM, &len);
193 AssertRCReturn(rc, rc);
194
195 if (len != sizeof(*pClient))
196 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
197
198 rc = SSMR3GetMem(pSSM, pClient, sizeof(*pClient));
199 AssertRCReturn(rc, rc);
200
201 /* We don't actually (fully) restore the state; we simply check if the current state is as we it expect it to be. */
202 for (int i=0;i<SHFL_MAX_MAPPINGS;i++)
203 {
204 /* Load the saved mapping description and try to find it in the mappings. */
205 MAPPING mapping;
206 memset (&mapping, 0, sizeof (mapping));
207
208 /* restore the folder mapping counter. */
209 rc = SSMR3GetU32(pSSM, &mapping.cMappings);
210 AssertRCReturn(rc, rc);
211
212 rc = SSMR3GetBool(pSSM, &mapping.fValid);
213 AssertRCReturn(rc, rc);
214
215 if (mapping.fValid)
216 {
217 uint32_t cbFolderName;
218 PSHFLSTRING pFolderName;
219
220 uint32_t cbMapName;
221 PSHFLSTRING pMapName;
222
223 /* Load the host path name. */
224 rc = SSMR3GetU32(pSSM, &cbFolderName);
225 AssertRCReturn(rc, rc);
226
227 pFolderName = (PSHFLSTRING)RTMemAlloc(cbFolderName);
228 AssertReturn(pFolderName != NULL, VERR_NO_MEMORY);
229
230 rc = SSMR3GetMem(pSSM, pFolderName, cbFolderName);
231 AssertRCReturn(rc, rc);
232
233 /* Load the map name. */
234 rc = SSMR3GetU32(pSSM, &cbMapName);
235 AssertRCReturn(rc, rc);
236
237 pMapName = (PSHFLSTRING)RTMemAlloc(cbMapName);
238 AssertReturn(pMapName != NULL, VERR_NO_MEMORY);
239
240 rc = SSMR3GetMem(pSSM, pMapName, cbMapName);
241 AssertRCReturn(rc, rc);
242
243 rc = SSMR3GetBool(pSSM, &mapping.fHostCaseSensitive);
244 AssertRCReturn(rc, rc);
245
246 rc = SSMR3GetBool(pSSM, &mapping.fGuestCaseSensitive);
247 AssertRCReturn(rc, rc);
248
249 mapping.pFolderName = pFolderName;
250 mapping.pMapName = pMapName;
251
252 /* 'i' is the root handle of the saved mapping. */
253 rc = vbsfMappingLoaded (&mapping, i);
254
255 RTMemFree(pMapName);
256 RTMemFree(pFolderName);
257
258 AssertRCReturn(rc, rc);
259 }
260 }
261 LogRel(("SharedFolders host service: success\n"));
262 return VINF_SUCCESS;
263}
264
265static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
266{
267 int rc = VINF_SUCCESS;
268
269 Log(("svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n", u32ClientID, u32Function, cParms, paParms));
270
271 SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
272
273 bool fAsynchronousProcessing = false;
274
275#ifdef DEBUG
276 uint32_t i;
277
278 for (i = 0; i < cParms; i++)
279 {
280 /** @todo parameters other than 32 bit */
281 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
282 }
283#endif
284
285 switch (u32Function)
286 {
287 case SHFL_FN_QUERY_MAPPINGS:
288 {
289 Log(("svcCall: SHFL_FN_QUERY_MAPPINGS\n"));
290
291 /* Verify parameter count and types. */
292 if (cParms != SHFL_CPARMS_QUERY_MAPPINGS)
293 {
294 rc = VERR_INVALID_PARAMETER;
295 }
296 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
297 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* numberOfMappings */
298 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* mappings */
299 )
300 {
301 rc = VERR_INVALID_PARAMETER;
302 }
303 else
304 {
305 /* Fetch parameters. */
306 uint32_t fu32Flags = paParms[0].u.uint32;
307 uint32_t cMappings = paParms[1].u.uint32;
308 SHFLMAPPING *pMappings = (SHFLMAPPING *)paParms[2].u.pointer.addr;
309 uint32_t cbMappings = paParms[2].u.pointer.size;
310
311 /* Verify parameters values. */
312 if ( (fu32Flags & ~SHFL_MF_UTF8) != 0
313 || cbMappings / sizeof (SHFLMAPPING) < cMappings
314 )
315 {
316 rc = VERR_INVALID_PARAMETER;
317 }
318 else
319 {
320 /* Execute the function. */
321 if (fu32Flags & SHFL_MF_UTF8)
322 {
323 pClient->fu32Flags |= SHFL_CF_UTF8;
324 }
325
326 rc = vbsfMappingsQuery (pClient, pMappings, &cMappings);
327
328 if (RT_SUCCESS(rc))
329 {
330 /* Update parameters.*/
331 paParms[1].u.uint32 = cMappings;
332 }
333 }
334 }
335
336
337 } break;
338
339 case SHFL_FN_QUERY_MAP_NAME:
340 {
341 Log(("svcCall: SHFL_FN_QUERY_MAP_NAME\n"));
342
343 /* Verify parameter count and types. */
344 if (cParms != SHFL_CPARMS_QUERY_MAP_NAME)
345 {
346 rc = VERR_INVALID_PARAMETER;
347 }
348 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
349 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* name */
350 )
351 {
352 rc = VERR_INVALID_PARAMETER;
353 }
354 else
355 {
356 /* Fetch parameters. */
357 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
358 SHFLSTRING *pString = (SHFLSTRING *)paParms[1].u.pointer.addr;
359
360 /* Verify parameters values. */
361 if (!ShflStringIsValid(pString, paParms[1].u.pointer.size))
362 {
363 rc = VERR_INVALID_PARAMETER;
364 }
365 else
366 {
367 /* Execute the function. */
368 rc = vbsfMappingsQueryName (pClient, root, pString);
369
370 if (RT_SUCCESS(rc))
371 {
372 /* Update parameters.*/
373 ; /* none */
374 }
375 }
376 }
377
378 } break;
379
380 case SHFL_FN_CREATE:
381 {
382 Log(("svcCall: SHFL_FN_CREATE\n"));
383
384 /* Verify parameter count and types. */
385 if (cParms != SHFL_CPARMS_CREATE)
386 {
387 rc = VERR_INVALID_PARAMETER;
388 }
389 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
390 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* path */
391 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* parms */
392 )
393 {
394 Log(("Invalid parameters types\n"));
395 rc = VERR_INVALID_PARAMETER;
396 }
397 else
398 {
399 /* Fetch parameters. */
400 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
401 SHFLSTRING *pPath = (SHFLSTRING *)paParms[1].u.pointer.addr;
402 uint32_t cbPath = paParms[1].u.pointer.size;
403 SHFLCREATEPARMS *pParms = (SHFLCREATEPARMS *)paParms[2].u.pointer.addr;
404 uint32_t cbParms = paParms[2].u.pointer.size;
405
406 /* Verify parameters values. */
407 if ( !ShflStringIsValid(pPath, cbPath)
408 || (cbParms != sizeof (SHFLCREATEPARMS))
409 )
410 {
411 AssertMsgFailed (("Invalid parameters cbPath or cbParms (%x, %x - expected >=%x, %x)\n",
412 cbPath, cbParms, sizeof(SHFLSTRING), sizeof (SHFLCREATEPARMS)));
413 rc = VERR_INVALID_PARAMETER;
414 }
415 else
416 {
417 /* Execute the function. */
418
419 rc = vbsfCreate (pClient, root, pPath, cbPath, pParms);
420
421 if (RT_SUCCESS(rc))
422 {
423 /* Update parameters.*/
424 ; /* none */
425 }
426 }
427 }
428 break;
429 }
430
431 case SHFL_FN_CLOSE:
432 {
433 Log(("svcCall: SHFL_FN_CLOSE\n"));
434
435 /* Verify parameter count and types. */
436 if (cParms != SHFL_CPARMS_CLOSE)
437 {
438 rc = VERR_INVALID_PARAMETER;
439 }
440 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
441 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
442 )
443 {
444 rc = VERR_INVALID_PARAMETER;
445 }
446 else
447 {
448 /* Fetch parameters. */
449 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
450 SHFLHANDLE Handle = paParms[1].u.uint64;
451
452 /* Verify parameters values. */
453 if (Handle == SHFL_HANDLE_ROOT)
454 {
455 rc = VERR_INVALID_PARAMETER;
456 }
457 else
458 if (Handle == SHFL_HANDLE_NIL)
459 {
460 AssertMsgFailed(("Invalid handle!!!!\n"));
461 rc = VERR_INVALID_HANDLE;
462 }
463 else
464 {
465 /* Execute the function. */
466
467 rc = vbsfClose (pClient, root, Handle);
468
469 if (RT_SUCCESS(rc))
470 {
471 /* Update parameters.*/
472 ; /* none */
473 }
474 }
475 }
476 break;
477
478 }
479
480 /** Read object content. */
481 case SHFL_FN_READ:
482 Log(("svcCall: SHFL_FN_READ\n"));
483
484 /* Verify parameter count and types. */
485 if (cParms != SHFL_CPARMS_READ)
486 {
487 rc = VERR_INVALID_PARAMETER;
488 }
489 else
490 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
491 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
492 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */
493 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* count */
494 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
495 )
496 {
497 rc = VERR_INVALID_PARAMETER;
498 }
499 else
500 {
501 /* Fetch parameters. */
502 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
503 SHFLHANDLE Handle = paParms[1].u.uint64;
504 uint64_t offset = paParms[2].u.uint64;
505 uint32_t count = paParms[3].u.uint32;
506 uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr;
507
508 /* Verify parameters values. */
509 if ( Handle == SHFL_HANDLE_ROOT
510 || count > paParms[4].u.pointer.size
511 )
512 {
513 rc = VERR_INVALID_PARAMETER;
514 }
515 else
516 if (Handle == SHFL_HANDLE_NIL)
517 {
518 AssertMsgFailed(("Invalid handle!!!!\n"));
519 rc = VERR_INVALID_HANDLE;
520 }
521 else
522 {
523 /* Execute the function. */
524 if (pStatusLed)
525 {
526 Assert(pStatusLed->u32Magic == PDMLED_MAGIC);
527 pStatusLed->Asserted.s.fReading = pStatusLed->Actual.s.fReading = 1;
528 }
529
530 rc = vbsfRead (pClient, root, Handle, offset, &count, pBuffer);
531 if (pStatusLed)
532 pStatusLed->Actual.s.fReading = 0;
533
534 if (RT_SUCCESS(rc))
535 {
536 /* Update parameters.*/
537 paParms[3].u.uint32 = count;
538 }
539 else
540 {
541 paParms[3].u.uint32 = 0; /* nothing read */
542 }
543 }
544 }
545 break;
546
547 /** Write new object content. */
548 case SHFL_FN_WRITE:
549 Log(("svcCall: SHFL_FN_WRITE\n"));
550
551 /* Verify parameter count and types. */
552 if (cParms != SHFL_CPARMS_WRITE)
553 {
554 rc = VERR_INVALID_PARAMETER;
555 }
556 else
557 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
558 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
559 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */
560 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* count */
561 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
562 )
563 {
564 rc = VERR_INVALID_PARAMETER;
565 }
566 else
567 {
568 /* Fetch parameters. */
569 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
570 SHFLHANDLE Handle = paParms[1].u.uint64;
571 uint64_t offset = paParms[2].u.uint64;
572 uint32_t count = paParms[3].u.uint32;
573 uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr;
574
575 /* Verify parameters values. */
576 if ( Handle == SHFL_HANDLE_ROOT
577 || count > paParms[4].u.pointer.size
578 )
579 {
580 rc = VERR_INVALID_PARAMETER;
581 }
582 else
583 if (Handle == SHFL_HANDLE_NIL)
584 {
585 AssertMsgFailed(("Invalid handle!!!!\n"));
586 rc = VERR_INVALID_HANDLE;
587 }
588 else
589 {
590 /* Execute the function. */
591 if (pStatusLed)
592 {
593 Assert(pStatusLed->u32Magic == PDMLED_MAGIC);
594 pStatusLed->Asserted.s.fWriting = pStatusLed->Actual.s.fWriting = 1;
595 }
596
597 rc = vbsfWrite (pClient, root, Handle, offset, &count, pBuffer);
598 if (pStatusLed)
599 pStatusLed->Actual.s.fWriting = 0;
600
601 if (RT_SUCCESS(rc))
602 {
603 /* Update parameters.*/
604 paParms[3].u.uint32 = count;
605 }
606 else
607 {
608 paParms[3].u.uint32 = 0; /* nothing read */
609 }
610 }
611 }
612 break;
613
614 /** Lock/unlock a range in the object. */
615 case SHFL_FN_LOCK:
616 Log(("svcCall: SHFL_FN_LOCK\n"));
617
618 /* Verify parameter count and types. */
619 if (cParms != SHFL_CPARMS_LOCK)
620 {
621 rc = VERR_INVALID_PARAMETER;
622 }
623 else
624 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
625 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
626 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */
627 || paParms[3].type != VBOX_HGCM_SVC_PARM_64BIT /* length */
628 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
629 )
630 {
631 rc = VERR_INVALID_PARAMETER;
632 }
633 else
634 {
635 /* Fetch parameters. */
636 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
637 SHFLHANDLE Handle = paParms[1].u.uint64;
638 uint64_t offset = paParms[2].u.uint64;
639 uint64_t length = paParms[3].u.uint64;
640 uint32_t flags = paParms[4].u.uint32;
641
642 /* Verify parameters values. */
643 if (Handle == SHFL_HANDLE_ROOT)
644 {
645 rc = VERR_INVALID_PARAMETER;
646 }
647 else
648 if (Handle == SHFL_HANDLE_NIL)
649 {
650 AssertMsgFailed(("Invalid handle!!!!\n"));
651 rc = VERR_INVALID_HANDLE;
652 }
653 else if (flags & SHFL_LOCK_WAIT)
654 {
655 /* @todo This should be properly implemented by the shared folders service.
656 * The service thread must never block. If an operation requires
657 * blocking, it must be processed by another thread and when it is
658 * completed, the another thread must call
659 *
660 * g_pHelpers->pfnCallComplete (callHandle, rc);
661 *
662 * The operation is async.
663 * fAsynchronousProcessing = true;
664 */
665
666 /* Here the operation must be posted to another thread. At the moment it is not implemented.
667 * Until it is implemented, try to perform the operation without waiting.
668 */
669 flags &= ~SHFL_LOCK_WAIT;
670
671 /* Execute the function. */
672 if ((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL)
673 rc = vbsfUnlock(pClient, root, Handle, offset, length, flags);
674 else
675 rc = vbsfLock(pClient, root, Handle, offset, length, flags);
676
677 if (RT_SUCCESS(rc))
678 {
679 /* Update parameters.*/
680 /* none */
681 }
682 }
683 else
684 {
685 /* Execute the function. */
686 if ((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL)
687 rc = vbsfUnlock(pClient, root, Handle, offset, length, flags);
688 else
689 rc = vbsfLock(pClient, root, Handle, offset, length, flags);
690
691 if (RT_SUCCESS(rc))
692 {
693 /* Update parameters.*/
694 /* none */
695 }
696 }
697 }
698 break;
699
700 /** List object content. */
701 case SHFL_FN_LIST:
702 {
703 Log(("svcCall: SHFL_FN_LIST\n"));
704
705 /* Verify parameter count and types. */
706 if (cParms != SHFL_CPARMS_LIST)
707 {
708 rc = VERR_INVALID_PARAMETER;
709 }
710 else
711 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
712 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
713 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
714 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* cb */
715 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* pPath */
716 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
717 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* resumePoint */
718 || paParms[7].type != VBOX_HGCM_SVC_PARM_32BIT /* cFiles (out) */
719 )
720 {
721 rc = VERR_INVALID_PARAMETER;
722 }
723 else
724 {
725 /* Fetch parameters. */
726 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
727 SHFLHANDLE Handle = paParms[1].u.uint64;
728 uint32_t flags = paParms[2].u.uint32;
729 uint32_t length = paParms[3].u.uint32;
730 SHFLSTRING *pPath = (paParms[4].u.pointer.size == 0) ? 0 : (SHFLSTRING *)paParms[4].u.pointer.addr;
731 uint8_t *pBuffer = (uint8_t *)paParms[5].u.pointer.addr;
732 uint32_t resumePoint = paParms[6].u.uint32;
733 uint32_t cFiles = 0;
734
735 /* Verify parameters values. */
736 if ( (length < sizeof (SHFLDIRINFO))
737 || length > paParms[5].u.pointer.size
738 || !ShflStringIsValidOrNull(pPath, paParms[4].u.pointer.size)
739 )
740 {
741 rc = VERR_INVALID_PARAMETER;
742 }
743 else
744 {
745 if (pStatusLed)
746 {
747 Assert(pStatusLed->u32Magic == PDMLED_MAGIC);
748 pStatusLed->Asserted.s.fReading = pStatusLed->Actual.s.fReading = 1;
749 }
750
751 /* Execute the function. */
752 rc = vbsfDirList (pClient, root, Handle, pPath, flags, &length, pBuffer, &resumePoint, &cFiles);
753
754 if (pStatusLed)
755 pStatusLed->Actual.s.fReading = 0;
756
757 if (rc == VERR_NO_MORE_FILES && cFiles != 0)
758 rc = VINF_SUCCESS; /* Successfully return these files. */
759
760 if (RT_SUCCESS(rc))
761 {
762 /* Update parameters.*/
763 paParms[3].u.uint32 = length;
764 paParms[6].u.uint32 = resumePoint;
765 paParms[7].u.uint32 = cFiles;
766 }
767 else
768 {
769 paParms[3].u.uint32 = 0; /* nothing read */
770 paParms[6].u.uint32 = 0;
771 paParms[7].u.uint32 = cFiles;
772 }
773 }
774 }
775 break;
776 }
777
778 /* Legacy interface */
779 case SHFL_FN_MAP_FOLDER_OLD:
780 {
781 Log(("svcCall: SHFL_FN_MAP_FOLDER_OLD\n"));
782
783 /* Verify parameter count and types. */
784 if (cParms != SHFL_CPARMS_MAP_FOLDER_OLD)
785 {
786 rc = VERR_INVALID_PARAMETER;
787 }
788 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* path */
789 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
790 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* delimiter */
791 )
792 {
793 rc = VERR_INVALID_PARAMETER;
794 }
795 else
796 {
797 /* Fetch parameters. */
798 PSHFLSTRING pszMapName = (PSHFLSTRING)paParms[0].u.pointer.addr;
799 SHFLROOT root = (SHFLROOT)paParms[1].u.uint32;
800 RTUTF16 delimiter = (RTUTF16)paParms[2].u.uint32;
801
802 /* Verify parameters values. */
803 if (!ShflStringIsValid(pszMapName, paParms[0].u.pointer.size))
804 {
805 rc = VERR_INVALID_PARAMETER;
806 }
807 else
808 {
809 /* Execute the function. */
810 rc = vbsfMapFolder (pClient, pszMapName, delimiter, false, &root);
811
812 if (RT_SUCCESS(rc))
813 {
814 /* Update parameters.*/
815 paParms[1].u.uint32 = root;
816 }
817 }
818 }
819 break;
820 }
821
822 case SHFL_FN_MAP_FOLDER:
823 {
824 Log(("svcCall: SHFL_FN_MAP_FOLDER\n"));
825 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
826 LogRel(("SharedFolders host service: request to map folder %S\n",
827 ((PSHFLSTRING)paParms[0].u.pointer.addr)->String.utf8));
828 else
829 LogRel(("SharedFolders host service: request to map folder %lS\n",
830 ((PSHFLSTRING)paParms[0].u.pointer.addr)->String.ucs2));
831
832 /* Verify parameter count and types. */
833 if (cParms != SHFL_CPARMS_MAP_FOLDER)
834 {
835 rc = VERR_INVALID_PARAMETER;
836 }
837 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* path */
838 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
839 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* delimiter */
840 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* fCaseSensitive */
841 )
842 {
843 rc = VERR_INVALID_PARAMETER;
844 }
845 else
846 {
847 /* Fetch parameters. */
848 PSHFLSTRING pszMapName = (PSHFLSTRING)paParms[0].u.pointer.addr;
849 SHFLROOT root = (SHFLROOT)paParms[1].u.uint32;
850 RTUTF16 delimiter = (RTUTF16)paParms[2].u.uint32;
851 bool fCaseSensitive = !!paParms[3].u.uint32;
852
853 /* Verify parameters values. */
854 if (!ShflStringIsValid(pszMapName, paParms[0].u.pointer.size))
855 {
856 rc = VERR_INVALID_PARAMETER;
857 }
858 else
859 {
860
861 /* Execute the function. */
862 rc = vbsfMapFolder (pClient, pszMapName, delimiter, fCaseSensitive, &root);
863
864 if (RT_SUCCESS(rc))
865 {
866 /* Update parameters.*/
867 paParms[1].u.uint32 = root;
868 }
869 }
870 }
871 LogRel(("SharedFolders host service: map operation result %Rrc.\n", rc));
872 if (RT_SUCCESS(rc))
873 LogRel((" Mapped to handle %d.\n", paParms[1].u.uint32));
874 break;
875 }
876
877 case SHFL_FN_UNMAP_FOLDER:
878 {
879 Log(("svcCall: SHFL_FN_UNMAP_FOLDER\n"));
880 LogRel(("SharedFolders host service: request to unmap folder handle %d\n",
881 paParms[0].u.uint32));
882
883 /* Verify parameter count and types. */
884 if (cParms != SHFL_CPARMS_UNMAP_FOLDER)
885 {
886 rc = VERR_INVALID_PARAMETER;
887 }
888 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
889 )
890 {
891 rc = VERR_INVALID_PARAMETER;
892 }
893 else
894 {
895 /* Fetch parameters. */
896 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
897
898 /* Execute the function. */
899 rc = vbsfUnmapFolder (pClient, root);
900
901 if (RT_SUCCESS(rc))
902 {
903 /* Update parameters.*/
904 /* nothing */
905 }
906 }
907 LogRel(("SharedFolders host service: unmap operation result %Rrc.\n", rc));
908 break;
909 }
910
911 /** Query/set object information. */
912 case SHFL_FN_INFORMATION:
913 {
914 Log(("svcCall: SHFL_FN_INFORMATION\n"));
915
916 /* Verify parameter count and types. */
917 if (cParms != SHFL_CPARMS_INFORMATION)
918 {
919 rc = VERR_INVALID_PARAMETER;
920 }
921 else
922 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
923 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
924 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
925 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* cb */
926 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
927 )
928 {
929 rc = VERR_INVALID_PARAMETER;
930 }
931 else
932 {
933 /* Fetch parameters. */
934 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
935 SHFLHANDLE Handle = paParms[1].u.uint64;
936 uint32_t flags = paParms[2].u.uint32;
937 uint32_t length = paParms[3].u.uint32;
938 uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr;
939
940 /* Verify parameters values. */
941 if (length > paParms[4].u.pointer.size)
942 {
943 rc = VERR_INVALID_PARAMETER;
944 }
945 else
946 {
947 /* Execute the function. */
948 if (flags & SHFL_INFO_SET)
949 rc = vbsfSetFSInfo (pClient, root, Handle, flags, &length, pBuffer);
950 else /* SHFL_INFO_GET */
951 rc = vbsfQueryFSInfo (pClient, root, Handle, flags, &length, pBuffer);
952
953 if (RT_SUCCESS(rc))
954 {
955 /* Update parameters.*/
956 paParms[3].u.uint32 = length;
957 }
958 else
959 {
960 paParms[3].u.uint32 = 0; /* nothing read */
961 }
962 }
963 }
964 break;
965 }
966
967 /** Remove or rename object */
968 case SHFL_FN_REMOVE:
969 {
970 Log(("svcCall: SHFL_FN_REMOVE\n"));
971
972 /* Verify parameter count and types. */
973 if (cParms != SHFL_CPARMS_REMOVE)
974 {
975 rc = VERR_INVALID_PARAMETER;
976 }
977 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
978 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* path */
979 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
980 )
981 {
982 rc = VERR_INVALID_PARAMETER;
983 }
984 else
985 {
986 /* Fetch parameters. */
987 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
988 SHFLSTRING *pPath = (SHFLSTRING *)paParms[1].u.pointer.addr;
989 uint32_t cbPath = paParms[1].u.pointer.size;
990 uint32_t flags = paParms[2].u.uint32;
991
992 /* Verify parameters values. */
993 if (!ShflStringIsValid(pPath, cbPath))
994 {
995 rc = VERR_INVALID_PARAMETER;
996 }
997 else
998 {
999 /* Execute the function. */
1000
1001 rc = vbsfRemove (pClient, root, pPath, cbPath, flags);
1002 if (RT_SUCCESS(rc))
1003 {
1004 /* Update parameters.*/
1005 ; /* none */
1006 }
1007 }
1008 }
1009 break;
1010 }
1011
1012 case SHFL_FN_RENAME:
1013 {
1014 Log(("svcCall: SHFL_FN_RENAME\n"));
1015
1016 /* Verify parameter count and types. */
1017 if (cParms != SHFL_CPARMS_RENAME)
1018 {
1019 rc = VERR_INVALID_PARAMETER;
1020 }
1021 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
1022 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* src */
1023 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* dest */
1024 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
1025 )
1026 {
1027 rc = VERR_INVALID_PARAMETER;
1028 }
1029 else
1030 {
1031 /* Fetch parameters. */
1032 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
1033 SHFLSTRING *pSrc = (SHFLSTRING *)paParms[1].u.pointer.addr;
1034 SHFLSTRING *pDest = (SHFLSTRING *)paParms[2].u.pointer.addr;
1035 uint32_t flags = paParms[3].u.uint32;
1036
1037 /* Verify parameters values. */
1038 if ( !ShflStringIsValid(pSrc, paParms[1].u.pointer.size)
1039 || !ShflStringIsValid(pDest, paParms[2].u.pointer.size)
1040 )
1041 {
1042 rc = VERR_INVALID_PARAMETER;
1043 }
1044 else
1045 {
1046 /* Execute the function. */
1047 rc = vbsfRename (pClient, root, pSrc, pDest, flags);
1048 if (RT_SUCCESS(rc))
1049 {
1050 /* Update parameters.*/
1051 ; /* none */
1052 }
1053 }
1054 }
1055 break;
1056 }
1057
1058 case SHFL_FN_FLUSH:
1059 {
1060 Log(("svcCall: SHFL_FN_FLUSH\n"));
1061
1062 /* Verify parameter count and types. */
1063 if (cParms != SHFL_CPARMS_FLUSH)
1064 {
1065 rc = VERR_INVALID_PARAMETER;
1066 }
1067 else
1068 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
1069 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
1070 )
1071 {
1072 rc = VERR_INVALID_PARAMETER;
1073 }
1074 else
1075 {
1076 /* Fetch parameters. */
1077 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
1078 SHFLHANDLE Handle = paParms[1].u.uint64;
1079
1080 /* Verify parameters values. */
1081 if (Handle == SHFL_HANDLE_ROOT)
1082 {
1083 rc = VERR_INVALID_PARAMETER;
1084 }
1085 else
1086 if (Handle == SHFL_HANDLE_NIL)
1087 {
1088 AssertMsgFailed(("Invalid handle!!!!\n"));
1089 rc = VERR_INVALID_HANDLE;
1090 }
1091 else
1092 {
1093 /* Execute the function. */
1094
1095 rc = vbsfFlush (pClient, root, Handle);
1096
1097 if (RT_SUCCESS(rc))
1098 {
1099 /* Nothing to do */
1100 }
1101 }
1102 }
1103 } break;
1104
1105 case SHFL_FN_SET_UTF8:
1106 {
1107 pClient->fu32Flags |= SHFL_CF_UTF8;
1108 rc = VINF_SUCCESS;
1109 break;
1110 }
1111
1112 default:
1113 {
1114 rc = VERR_NOT_IMPLEMENTED;
1115 break;
1116 }
1117 }
1118
1119 LogFlow(("svcCall: rc = %Rrc\n", rc));
1120
1121 if ( !fAsynchronousProcessing
1122 || RT_FAILURE (rc))
1123 {
1124 /* Complete the operation if it was unsuccessful or
1125 * it was processed synchronously.
1126 */
1127 g_pHelpers->pfnCallComplete (callHandle, rc);
1128 }
1129
1130 LogFlow(("\n")); /* Add a new line to differentiate between calls more easily. */
1131}
1132
1133/*
1134 * We differentiate between a function handler for the guest and one for the host. The guest is not allowed to add or remove mappings for obvious security reasons.
1135 */
1136static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
1137{
1138 int rc = VINF_SUCCESS;
1139
1140 Log(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
1141
1142#ifdef DEBUG
1143 uint32_t i;
1144
1145 for (i = 0; i < cParms; i++)
1146 {
1147 /** @todo parameters other than 32 bit */
1148 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
1149 }
1150#endif
1151
1152 switch (u32Function)
1153 {
1154 case SHFL_FN_ADD_MAPPING:
1155 {
1156 Log(("svcCall: SHFL_FN_ADD_MAPPING\n"));
1157 LogRel(("SharedFolders host service: adding host mapping.\n"));
1158 LogRel((" Host path %lS, map name %lS, writable %d\n",
1159 ((SHFLSTRING *)paParms[0].u.pointer.addr)->String.ucs2,
1160 ((SHFLSTRING *)paParms[1].u.pointer.addr)->String.ucs2,
1161 paParms[2].u.uint32));
1162
1163 /* Verify parameter count and types. */
1164 if (cParms != SHFL_CPARMS_ADD_MAPPING)
1165 {
1166 rc = VERR_INVALID_PARAMETER;
1167 }
1168 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* host folder name */
1169 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* guest map name */
1170 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* fWritable */
1171 )
1172 {
1173 rc = VERR_INVALID_PARAMETER;
1174 }
1175 else
1176 {
1177 /* Fetch parameters. */
1178 SHFLSTRING *pFolderName = (SHFLSTRING *)paParms[0].u.pointer.addr;
1179 SHFLSTRING *pMapName = (SHFLSTRING *)paParms[1].u.pointer.addr;
1180 uint32_t fWritable = paParms[2].u.uint32;
1181
1182 /* Verify parameters values. */
1183 if ( !ShflStringIsValid(pFolderName, paParms[0].u.pointer.size)
1184 || !ShflStringIsValid(pMapName, paParms[1].u.pointer.size)
1185 )
1186 {
1187 rc = VERR_INVALID_PARAMETER;
1188 }
1189 else
1190 {
1191 /* Execute the function. */
1192 rc = vbsfMappingsAdd (pFolderName, pMapName, fWritable);
1193
1194 if (RT_SUCCESS(rc))
1195 {
1196 /* Update parameters.*/
1197 ; /* none */
1198 }
1199 }
1200 }
1201 LogRel(("SharedFolders host service: add mapping result %Rrc\n", rc));
1202 break;
1203 }
1204
1205 case SHFL_FN_REMOVE_MAPPING:
1206 {
1207 Log(("svcCall: SHFL_FN_REMOVE_MAPPING\n"));
1208 LogRel(("SharedFolders host service: removing host mapping %lS\n",
1209 ((SHFLSTRING *)paParms[0].u.pointer.addr)->String.ucs2));
1210
1211 /* Verify parameter count and types. */
1212 if (cParms != SHFL_CPARMS_REMOVE_MAPPING)
1213 {
1214 rc = VERR_INVALID_PARAMETER;
1215 }
1216 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* folder name */
1217 )
1218 {
1219 rc = VERR_INVALID_PARAMETER;
1220 }
1221 else
1222 {
1223 /* Fetch parameters. */
1224 SHFLSTRING *pString = (SHFLSTRING *)paParms[0].u.pointer.addr;
1225
1226 /* Verify parameters values. */
1227 if (!ShflStringIsValid(pString, paParms[0].u.pointer.size))
1228 {
1229 rc = VERR_INVALID_PARAMETER;
1230 }
1231 else
1232 {
1233 /* Execute the function. */
1234 rc = vbsfMappingsRemove (pString);
1235
1236 if (RT_SUCCESS(rc))
1237 {
1238 /* Update parameters.*/
1239 ; /* none */
1240 }
1241 }
1242 }
1243 LogRel(("SharedFolders host service: remove mapping result %Rrc\n", rc));
1244 break;
1245 }
1246
1247 case SHFL_FN_SET_STATUS_LED:
1248 {
1249 Log(("svcCall: SHFL_FN_SET_STATUS_LED\n"));
1250
1251 /* Verify parameter count and types. */
1252 if (cParms != SHFL_CPARMS_SET_STATUS_LED)
1253 {
1254 rc = VERR_INVALID_PARAMETER;
1255 }
1256 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* folder name */
1257 )
1258 {
1259 rc = VERR_INVALID_PARAMETER;
1260 }
1261 else
1262 {
1263 /* Fetch parameters. */
1264 PPDMLED pLed = (PPDMLED)paParms[0].u.pointer.addr;
1265 uint32_t cbLed = paParms[0].u.pointer.size;
1266
1267 /* Verify parameters values. */
1268 if ( (cbLed != sizeof (PDMLED))
1269 )
1270 {
1271 rc = VERR_INVALID_PARAMETER;
1272 }
1273 else
1274 {
1275 /* Execute the function. */
1276 pStatusLed = pLed;
1277 rc = VINF_SUCCESS;
1278 }
1279 }
1280 break;
1281 }
1282
1283 default:
1284 rc = VERR_NOT_IMPLEMENTED;
1285 break;
1286 }
1287
1288 LogFlow(("svcHostCall: rc = %Rrc\n", rc));
1289 return rc;
1290}
1291
1292extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
1293{
1294 int rc = VINF_SUCCESS;
1295
1296 Log(("VBoxHGCMSvcLoad: ptable = %p\n", ptable));
1297
1298 if (!VALID_PTR(ptable))
1299 {
1300 LogRelFunc(("Bad value of ptable (%p) in shared folders service\n", ptable));
1301 rc = VERR_INVALID_PARAMETER;
1302 }
1303 else
1304 {
1305 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
1306
1307 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
1308 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
1309 {
1310 LogRelFunc(("version mismatch loading shared folders service: ptable->cbSize = %d, should be %d, ptable->u32Version = 0x%08X, should be 0x%08X\n", ptable->cbSize, sizeof (VBOXHGCMSVCFNTABLE), ptable->u32Version, VBOX_HGCM_SVC_VERSION));
1311 rc = VERR_VERSION_MISMATCH;
1312 }
1313 else
1314 {
1315 g_pHelpers = ptable->pHelpers;
1316
1317 ptable->cbClient = sizeof (SHFLCLIENTDATA);
1318
1319 ptable->pfnUnload = svcUnload;
1320 ptable->pfnConnect = svcConnect;
1321 ptable->pfnDisconnect = svcDisconnect;
1322 ptable->pfnCall = svcCall;
1323 ptable->pfnHostCall = svcHostCall;
1324 ptable->pfnSaveState = svcSaveState;
1325 ptable->pfnLoadState = svcLoadState;
1326 ptable->pvService = NULL;
1327 }
1328
1329 /* Init handle table */
1330 rc = vbsfInitHandleTable();
1331 AssertRC(rc);
1332
1333 vbsfMappingInit();
1334 }
1335
1336 return rc;
1337}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use