VirtualBox

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

Last change on this file since 21172 was 21172, checked in by vboxsync, 15 years ago

Shared folders host service: fixed load state failure, when the order of mappings is changed.

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