VirtualBox

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

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

HGCM service must not block: added todo for SHFL_LOCK_WAIT (Shared folders).

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