VirtualBox

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

Last change on this file since 75488 was 75407, checked in by vboxsync, 6 years ago

VBoxSharedFolders,VBoxService,VBoxTray: New go at auto mounting shared folders, now also at runtime. bugref:3544

  • Added three new functions to the shared folders service:
    1. query mountpoint and everything else about a shared folder.
    2. wait for folder (mappings) config changes.
    3. cancel such waits.
  • Relaxed some of the check wrt placeholder folders so that the GUI can succesfully make changes to a folder while it is being used. The old code would end up failing if the guest was using the folder because of a (placeholder) duplicate.
  • Ran into some weird weird flag passing between service.cpp and vbsfMappingsQuery via pClient->fu32Flags. Didn't make sense to me and clashed with a new flag I added for the wait cancellation, so I changed it to use a parameter (fOnlyAutoMounts) for the purpose.
  • Pointed out that vbsfMappingsQuery is weird in a the way it doesn't return an overflow indicator, meaning that the guest library wrapper's checks for VINF_BUFFER_OVERFLOW is pointless.
  • In VBoxService I've reimplemented the automounter subservice. Only tested with a windows 7 guest so far. Highlights:
    • Use host specified mount points / drive letters.
    • Adjust to changes in mapping configuration.
    • Mappings should be global on windows guests, given that VBoxService runs under the System user (only verified on Win7).
  • One TODO is that I would like to try relocate a mapping that's not on the specified mount point once the mount point is freed up.
  • VBoxTray no longer maps shared folder on startup.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.9 KB
Line 
1/* $Id: service.cpp 75407 2018-11-12 20:06:57Z vboxsync $ */
2/** @file
3 * Shared Folders - Host service entry points.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/shflsvc.h>
19
20
21#include "shfl.h"
22#include "mappings.h"
23#include "shflhandle.h"
24#include "vbsf.h"
25#include <iprt/alloc.h>
26#include <iprt/string.h>
27#include <iprt/assert.h>
28#include <VBox/AssertGuest.h>
29#include <VBox/vmm/ssm.h>
30#include <VBox/vmm/pdmifs.h>
31
32#define SHFL_SAVED_STATE_VERSION_FOLDERNAME_UTF16 2
33#define SHFL_SAVED_STATE_VERSION_PRE_AUTO_MOUNT_POINT 3
34#define SHFL_SAVED_STATE_VERSION 4
35
36
37/** @page pg_shfl_svc 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 identifier 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 vbsfFreeHandleTable();
84
85 return rc;
86}
87
88static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
89{
90 RT_NOREF2(u32ClientID, pvClient);
91 int rc = VINF_SUCCESS;
92
93 Log(("SharedFolders host service: connected, u32ClientID = %u\n", u32ClientID));
94
95 return rc;
96}
97
98static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
99{
100 RT_NOREF1(u32ClientID);
101 int rc = VINF_SUCCESS;
102 SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
103
104 Log(("SharedFolders host service: disconnected, u32ClientID = %u\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#ifndef UNITTEST /* Read this as not yet tested */
119 RT_NOREF1(u32ClientID);
120 SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
121
122 Log(("SharedFolders host service: saving state, u32ClientID = %u\n", u32ClientID));
123
124 int rc = SSMR3PutU32(pSSM, SHFL_SAVED_STATE_VERSION);
125 AssertRCReturn(rc, rc);
126
127 rc = SSMR3PutU32(pSSM, SHFL_MAX_MAPPINGS);
128 AssertRCReturn(rc, rc);
129
130 /* Save client structure length & contents */
131 rc = SSMR3PutU32(pSSM, sizeof(*pClient));
132 AssertRCReturn(rc, rc);
133
134 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
135 AssertRCReturn(rc, rc);
136
137 /* Save all the active mappings. */
138 for (int i=0;i<SHFL_MAX_MAPPINGS;i++)
139 {
140 /* Mapping are saved in the order of increasing root handle values. */
141 MAPPING *pFolderMapping = vbsfMappingGetByRoot(i);
142
143 rc = SSMR3PutU32(pSSM, pFolderMapping? pFolderMapping->cMappings: 0);
144 AssertRCReturn(rc, rc);
145
146 rc = SSMR3PutBool(pSSM, pFolderMapping? pFolderMapping->fValid: false);
147 AssertRCReturn(rc, rc);
148
149 if (pFolderMapping && pFolderMapping->fValid)
150 {
151 uint32_t len = (uint32_t)strlen(pFolderMapping->pszFolderName);
152 SSMR3PutU32(pSSM, len);
153 SSMR3PutStrZ(pSSM, pFolderMapping->pszFolderName);
154
155 len = ShflStringSizeOfBuffer(pFolderMapping->pMapName);
156 SSMR3PutU32(pSSM, len);
157 SSMR3PutMem(pSSM, pFolderMapping->pMapName, len);
158
159 SSMR3PutBool(pSSM, pFolderMapping->fHostCaseSensitive);
160
161 SSMR3PutBool(pSSM, pFolderMapping->fGuestCaseSensitive);
162
163 len = ShflStringSizeOfBuffer(pFolderMapping->pAutoMountPoint);
164 SSMR3PutU32(pSSM, len);
165 rc = SSMR3PutMem(pSSM, pFolderMapping->pAutoMountPoint, len);
166 AssertRCReturn(rc, rc);
167 }
168 }
169
170#else
171 RT_NOREF3(u32ClientID, pvClient, pSSM);
172#endif
173 return VINF_SUCCESS;
174}
175
176static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
177{
178#ifndef UNITTEST /* Read this as not yet tested */
179 RT_NOREF1(u32ClientID);
180 uint32_t nrMappings;
181 SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
182 uint32_t len, version;
183
184 Log(("SharedFolders host service: loading state, u32ClientID = %u\n", u32ClientID));
185
186 int rc = SSMR3GetU32(pSSM, &version);
187 AssertRCReturn(rc, rc);
188
189 if ( version > SHFL_SAVED_STATE_VERSION
190 || version < SHFL_SAVED_STATE_VERSION_FOLDERNAME_UTF16)
191 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
192
193 rc = SSMR3GetU32(pSSM, &nrMappings);
194 AssertRCReturn(rc, rc);
195 if (nrMappings != SHFL_MAX_MAPPINGS)
196 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
197
198 /* Restore the client data (flags + path delimiter at the moment) */
199 rc = SSMR3GetU32(pSSM, &len);
200 AssertRCReturn(rc, rc);
201
202 if (len != sizeof(*pClient))
203 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
204
205 rc = SSMR3GetMem(pSSM, pClient, sizeof(*pClient));
206 AssertRCReturn(rc, rc);
207
208 /* We don't actually (fully) restore the state; we simply check if the current state is as we it expect it to be. */
209 for (int i=0;i<SHFL_MAX_MAPPINGS;i++)
210 {
211 /* Load the saved mapping description and try to find it in the mappings. */
212 MAPPING mapping;
213 RT_ZERO(mapping);
214
215 /* restore the folder mapping counter. */
216 rc = SSMR3GetU32(pSSM, &mapping.cMappings);
217 AssertRCReturn(rc, rc);
218
219 rc = SSMR3GetBool(pSSM, &mapping.fValid);
220 AssertRCReturn(rc, rc);
221
222 if (mapping.fValid)
223 {
224 uint32_t cb;
225
226 /* Load the host path name. */
227 rc = SSMR3GetU32(pSSM, &cb);
228 AssertRCReturn(rc, rc);
229
230 char *pszFolderName;
231 if (version == SHFL_SAVED_STATE_VERSION_FOLDERNAME_UTF16)
232 {
233 AssertReturn(cb > SHFLSTRING_HEADER_SIZE && cb <= UINT16_MAX + SHFLSTRING_HEADER_SIZE && !(cb & 1),
234 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, "Bad folder name size: %#x\n", cb));
235 PSHFLSTRING pFolderName = (PSHFLSTRING)RTMemAlloc(cb);
236 AssertReturn(pFolderName != NULL, VERR_NO_MEMORY);
237
238 rc = SSMR3GetMem(pSSM, pFolderName, cb);
239 AssertRCReturn(rc, rc);
240 AssertReturn(pFolderName->u16Size < cb && pFolderName->u16Length < pFolderName->u16Size,
241 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
242 "Bad folder name string: %#x/%#x cb=%#x\n",
243 pFolderName->u16Size, pFolderName->u16Length, cb));
244
245 rc = RTUtf16ToUtf8(pFolderName->String.ucs2, &pszFolderName);
246 RTMemFree(pFolderName);
247 AssertRCReturn(rc, rc);
248 }
249 else
250 {
251 pszFolderName = (char *)RTStrAlloc(cb + 1);
252 AssertReturn(pszFolderName, VERR_NO_MEMORY);
253
254 rc = SSMR3GetStrZ(pSSM, pszFolderName, cb + 1);
255 AssertRCReturn(rc, rc);
256 mapping.pszFolderName = pszFolderName;
257 }
258
259 /* Load the map name. */
260 rc = SSMR3GetU32(pSSM, &cb);
261 AssertRCReturn(rc, rc);
262 AssertReturn(cb > SHFLSTRING_HEADER_SIZE && cb <= UINT16_MAX + SHFLSTRING_HEADER_SIZE && !(cb & 1),
263 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, "Bad map name size: %#x\n", cb));
264
265 PSHFLSTRING pMapName = (PSHFLSTRING)RTMemAlloc(cb);
266 AssertReturn(pMapName != NULL, VERR_NO_MEMORY);
267
268 rc = SSMR3GetMem(pSSM, pMapName, cb);
269 AssertRCReturn(rc, rc);
270 AssertReturn(pMapName->u16Size < cb && pMapName->u16Length < pMapName->u16Size,
271 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
272 "Bad map name string: %#x/%#x cb=%#x\n",
273 pMapName->u16Size, pMapName->u16Length, cb));
274
275 /* Load case sensitivity config. */
276 rc = SSMR3GetBool(pSSM, &mapping.fHostCaseSensitive);
277 AssertRCReturn(rc, rc);
278
279 rc = SSMR3GetBool(pSSM, &mapping.fGuestCaseSensitive);
280 AssertRCReturn(rc, rc);
281
282 /* Load the auto mount point. */
283 PSHFLSTRING pAutoMountPoint;
284 if (version > SHFL_SAVED_STATE_VERSION_PRE_AUTO_MOUNT_POINT)
285 {
286 rc = SSMR3GetU32(pSSM, &cb);
287 AssertRCReturn(rc, rc);
288 AssertReturn(cb > SHFLSTRING_HEADER_SIZE && cb <= UINT16_MAX + SHFLSTRING_HEADER_SIZE && !(cb & 1),
289 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, "Bad auto mount point size: %#x\n", cb));
290
291 pAutoMountPoint = (PSHFLSTRING)RTMemAlloc(cb);
292 AssertReturn(pAutoMountPoint != NULL, VERR_NO_MEMORY);
293
294 rc = SSMR3GetMem(pSSM, pAutoMountPoint, cb);
295 AssertRCReturn(rc, rc);
296 AssertReturn(pAutoMountPoint->u16Size < cb && pAutoMountPoint->u16Length < pAutoMountPoint->u16Size,
297 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
298 "Bad auto mount point string: %#x/%#x cb=%#x\n",
299 pAutoMountPoint->u16Size, pAutoMountPoint->u16Length, cb));
300
301 }
302 else
303 {
304 pAutoMountPoint = ShflStringDupUtf8("");
305 AssertReturn(pAutoMountPoint, VERR_NO_MEMORY);
306 }
307
308 mapping.pszFolderName = pszFolderName;
309 mapping.pMapName = pMapName;
310 mapping.pAutoMountPoint = pAutoMountPoint;
311
312 /* 'i' is the root handle of the saved mapping. */
313 rc = vbsfMappingLoaded (&mapping, i);
314 if (RT_FAILURE(rc))
315 {
316 LogRel(("SharedFolders host service: %Rrc loading %d [%ls] -> [%s]\n",
317 rc, i, pMapName->String.ucs2, pszFolderName));
318 }
319
320 RTMemFree(pAutoMountPoint);
321 RTMemFree(pMapName);
322 RTStrFree(pszFolderName);
323
324 AssertRCReturn(rc, rc);
325 }
326 }
327 Log(("SharedFolders host service: successfully loaded state\n"));
328#else
329 RT_NOREF3(u32ClientID, pvClient, pSSM);
330#endif
331 return VINF_SUCCESS;
332}
333
334static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
335 void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
336{
337 RT_NOREF1(u32ClientID);
338 int rc = VINF_SUCCESS;
339
340 Log(("SharedFolders host service: svcCall: u32ClientID = %u, fn = %u, cParms = %u, pparms = %p\n", u32ClientID, u32Function, cParms, paParms));
341
342 SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
343
344 bool fAsynchronousProcessing = false;
345
346#ifdef LOG_ENABLED
347 for (uint32_t i = 0; i < cParms; i++)
348 {
349 /** @todo parameters other than 32 bit */
350 Log((" pparms[%d]: type %u, value %u\n", i, paParms[i].type, paParms[i].u.uint32));
351 }
352#endif
353
354 switch (u32Function)
355 {
356 case SHFL_FN_QUERY_MAPPINGS:
357 {
358 Log(("SharedFolders host service: svcCall: SHFL_FN_QUERY_MAPPINGS\n"));
359
360 /* Verify parameter count and types. */
361 if (cParms != SHFL_CPARMS_QUERY_MAPPINGS)
362 {
363 rc = VERR_INVALID_PARAMETER;
364 }
365 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
366 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* numberOfMappings */
367 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* mappings */
368 )
369 {
370 rc = VERR_INVALID_PARAMETER;
371 }
372 else
373 {
374 /* Fetch parameters. */
375 uint32_t fu32Flags = paParms[0].u.uint32;
376 uint32_t cMappings = paParms[1].u.uint32;
377 SHFLMAPPING *pMappings = (SHFLMAPPING *)paParms[2].u.pointer.addr;
378 uint32_t cbMappings = paParms[2].u.pointer.size;
379
380 /* Verify parameters values. */
381 if ( (fu32Flags & ~SHFL_MF_MASK) != 0
382 || cbMappings / sizeof (SHFLMAPPING) != cMappings
383 )
384 {
385 rc = VERR_INVALID_PARAMETER;
386 }
387 else
388 {
389 /* Execute the function. */
390 if (fu32Flags & SHFL_MF_UTF8)
391 pClient->fu32Flags |= SHFL_CF_UTF8;
392 /// @todo r=bird: Someone please explain this amusing code (r63916):
393 //if (fu32Flags & SHFL_MF_AUTOMOUNT)
394 // pClient->fu32Flags |= SHFL_MF_AUTOMOUNT;
395 //
396 //rc = vbsfMappingsQuery(pClient, pMappings, &cMappings);
397
398 rc = vbsfMappingsQuery(pClient, RT_BOOL(fu32Flags & SHFL_MF_AUTOMOUNT), pMappings, &cMappings);
399 if (RT_SUCCESS(rc))
400 {
401 /* Report that there are more mappings to get if
402 * handed in buffer is too small. */
403 if (paParms[1].u.uint32 < cMappings)
404 rc = VINF_BUFFER_OVERFLOW;
405
406 /* Update parameters. */
407 paParms[1].u.uint32 = cMappings;
408 }
409 }
410 }
411
412
413 } break;
414
415 case SHFL_FN_QUERY_MAP_NAME:
416 {
417 Log(("SharedFolders host service: svcCall: SHFL_FN_QUERY_MAP_NAME\n"));
418
419 /* Verify parameter count and types. */
420 if (cParms != SHFL_CPARMS_QUERY_MAP_NAME)
421 {
422 rc = VERR_INVALID_PARAMETER;
423 }
424 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* Root. */
425 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* Name. */
426 )
427 {
428 rc = VERR_INVALID_PARAMETER;
429 }
430 else
431 {
432 /* Fetch parameters. */
433 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
434 SHFLSTRING *pString = (SHFLSTRING *)paParms[1].u.pointer.addr;
435
436 /* Verify parameters values. */
437 if (!ShflStringIsValidOut(pString, paParms[1].u.pointer.size))
438 {
439 rc = VERR_INVALID_PARAMETER;
440 }
441 else
442 {
443 /* Execute the function. */
444 rc = vbsfMappingsQueryName(pClient, root, pString);
445
446 if (RT_SUCCESS(rc))
447 {
448 /* Update parameters.*/
449 ; /* None. */
450 }
451 }
452 }
453
454 } break;
455
456 case SHFL_FN_CREATE:
457 {
458 Log(("SharedFolders host service: svcCall: SHFL_FN_CREATE\n"));
459
460 /* Verify parameter count and types. */
461 if (cParms != SHFL_CPARMS_CREATE)
462 {
463 rc = VERR_INVALID_PARAMETER;
464 }
465 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
466 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* path */
467 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* parms */
468 )
469 {
470 Log(("SharedFolders host service: Invalid parameters types\n"));
471 rc = VERR_INVALID_PARAMETER;
472 }
473 else
474 {
475 /* Fetch parameters. */
476 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
477 SHFLSTRING *pPath = (SHFLSTRING *)paParms[1].u.pointer.addr;
478 uint32_t cbPath = paParms[1].u.pointer.size;
479 SHFLCREATEPARMS *pParms = (SHFLCREATEPARMS *)paParms[2].u.pointer.addr;
480 uint32_t cbParms = paParms[2].u.pointer.size;
481
482 /* Verify parameters values. */
483 if ( !ShflStringIsValidIn(pPath, cbPath, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))
484 || (cbParms != sizeof (SHFLCREATEPARMS))
485 )
486 {
487 AssertMsgFailed (("Invalid parameters cbPath or cbParms (%x, %x - expected >=%x, %x)\n",
488 cbPath, cbParms, sizeof(SHFLSTRING), sizeof (SHFLCREATEPARMS)));
489 rc = VERR_INVALID_PARAMETER;
490 }
491 else
492 {
493 /* Execute the function. */
494 rc = vbsfCreate (pClient, root, pPath, cbPath, pParms);
495
496 if (RT_SUCCESS(rc))
497 {
498 /* Update parameters.*/
499 ; /* none */
500 }
501 }
502 }
503 break;
504 }
505
506 case SHFL_FN_CLOSE:
507 {
508 Log(("SharedFolders host service: svcCall: SHFL_FN_CLOSE\n"));
509
510 /* Verify parameter count and types. */
511 if (cParms != SHFL_CPARMS_CLOSE)
512 {
513 rc = VERR_INVALID_PARAMETER;
514 }
515 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
516 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
517 )
518 {
519 rc = VERR_INVALID_PARAMETER;
520 }
521 else
522 {
523 /* Fetch parameters. */
524 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
525 SHFLHANDLE Handle = paParms[1].u.uint64;
526
527 /* Verify parameters values. */
528 if (Handle == SHFL_HANDLE_ROOT)
529 {
530 rc = VERR_INVALID_PARAMETER;
531 }
532 else
533 if (Handle == SHFL_HANDLE_NIL)
534 {
535 AssertMsgFailed(("Invalid handle!\n"));
536 rc = VERR_INVALID_HANDLE;
537 }
538 else
539 {
540 /* Execute the function. */
541 rc = vbsfClose (pClient, root, Handle);
542
543 if (RT_SUCCESS(rc))
544 {
545 /* Update parameters.*/
546 ; /* none */
547 }
548 }
549 }
550 break;
551
552 }
553
554 /** Read object content. */
555 case SHFL_FN_READ:
556 Log(("SharedFolders host service: svcCall: SHFL_FN_READ\n"));
557
558 /* Verify parameter count and types. */
559 if (cParms != SHFL_CPARMS_READ)
560 {
561 rc = VERR_INVALID_PARAMETER;
562 }
563 else
564 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
565 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
566 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */
567 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* count */
568 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
569 )
570 {
571 rc = VERR_INVALID_PARAMETER;
572 }
573 else
574 {
575 /* Fetch parameters. */
576 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
577 SHFLHANDLE Handle = paParms[1].u.uint64;
578 uint64_t offset = paParms[2].u.uint64;
579 uint32_t count = paParms[3].u.uint32;
580 uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr;
581
582 /* Verify parameters values. */
583 if ( Handle == SHFL_HANDLE_ROOT
584 || count > paParms[4].u.pointer.size
585 )
586 {
587 rc = VERR_INVALID_PARAMETER;
588 }
589 else
590 if (Handle == SHFL_HANDLE_NIL)
591 {
592 AssertMsgFailed(("Invalid handle!\n"));
593 rc = VERR_INVALID_HANDLE;
594 }
595 else
596 {
597 /* Execute the function. */
598 if (pStatusLed)
599 {
600 Assert(pStatusLed->u32Magic == PDMLED_MAGIC);
601 pStatusLed->Asserted.s.fReading = pStatusLed->Actual.s.fReading = 1;
602 }
603
604 rc = vbsfRead (pClient, root, Handle, offset, &count, pBuffer);
605 if (pStatusLed)
606 pStatusLed->Actual.s.fReading = 0;
607
608 if (RT_SUCCESS(rc))
609 {
610 /* Update parameters.*/
611 paParms[3].u.uint32 = count;
612 }
613 else
614 {
615 paParms[3].u.uint32 = 0; /* nothing read */
616 }
617 }
618 }
619 break;
620
621 /** Write new object content. */
622 case SHFL_FN_WRITE:
623 Log(("SharedFolders host service: svcCall: SHFL_FN_WRITE\n"));
624
625 /* Verify parameter count and types. */
626 if (cParms != SHFL_CPARMS_WRITE)
627 {
628 rc = VERR_INVALID_PARAMETER;
629 }
630 else
631 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
632 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
633 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */
634 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* count */
635 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
636 )
637 {
638 rc = VERR_INVALID_PARAMETER;
639 }
640 else
641 {
642 /* Fetch parameters. */
643 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
644 SHFLHANDLE Handle = paParms[1].u.uint64;
645 uint64_t offset = paParms[2].u.uint64;
646 uint32_t count = paParms[3].u.uint32;
647 uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr;
648
649 /* Verify parameters values. */
650 if ( Handle == SHFL_HANDLE_ROOT
651 || count > paParms[4].u.pointer.size
652 )
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
663 {
664 /* Execute the function. */
665 if (pStatusLed)
666 {
667 Assert(pStatusLed->u32Magic == PDMLED_MAGIC);
668 pStatusLed->Asserted.s.fWriting = pStatusLed->Actual.s.fWriting = 1;
669 }
670
671 rc = vbsfWrite (pClient, root, Handle, offset, &count, pBuffer);
672 if (pStatusLed)
673 pStatusLed->Actual.s.fWriting = 0;
674
675 if (RT_SUCCESS(rc))
676 {
677 /* Update parameters.*/
678 paParms[3].u.uint32 = count;
679 }
680 else
681 {
682 paParms[3].u.uint32 = 0; /* nothing read */
683 }
684 }
685 }
686 break;
687
688 /** Lock/unlock a range in the object. */
689 case SHFL_FN_LOCK:
690 Log(("SharedFolders host service: svcCall: SHFL_FN_LOCK\n"));
691
692 /* Verify parameter count and types. */
693 if (cParms != SHFL_CPARMS_LOCK)
694 {
695 rc = VERR_INVALID_PARAMETER;
696 }
697 else
698 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
699 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
700 || paParms[2].type != VBOX_HGCM_SVC_PARM_64BIT /* offset */
701 || paParms[3].type != VBOX_HGCM_SVC_PARM_64BIT /* length */
702 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
703 )
704 {
705 rc = VERR_INVALID_PARAMETER;
706 }
707 else
708 {
709 /* Fetch parameters. */
710 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
711 SHFLHANDLE Handle = paParms[1].u.uint64;
712 uint64_t offset = paParms[2].u.uint64;
713 uint64_t length = paParms[3].u.uint64;
714 uint32_t flags = paParms[4].u.uint32;
715
716 /* Verify parameters values. */
717 if (Handle == SHFL_HANDLE_ROOT)
718 {
719 rc = VERR_INVALID_PARAMETER;
720 }
721 else
722 if (Handle == SHFL_HANDLE_NIL)
723 {
724 AssertMsgFailed(("Invalid handle!\n"));
725 rc = VERR_INVALID_HANDLE;
726 }
727 else if (flags & SHFL_LOCK_WAIT)
728 {
729 /** @todo This should be properly implemented by the shared folders service.
730 * The service thread must never block. If an operation requires
731 * blocking, it must be processed by another thread and when it is
732 * completed, the another thread must call
733 *
734 * g_pHelpers->pfnCallComplete (callHandle, rc);
735 *
736 * The operation is async.
737 * fAsynchronousProcessing = true;
738 */
739
740 /* Here the operation must be posted to another thread. At the moment it is not implemented.
741 * Until it is implemented, try to perform the operation without waiting.
742 */
743 flags &= ~SHFL_LOCK_WAIT;
744
745 /* Execute the function. */
746 if ((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL)
747 rc = vbsfUnlock(pClient, root, Handle, offset, length, flags);
748 else
749 rc = vbsfLock(pClient, root, Handle, offset, length, flags);
750
751 if (RT_SUCCESS(rc))
752 {
753 /* Update parameters.*/
754 /* none */
755 }
756 }
757 else
758 {
759 /* Execute the function. */
760 if ((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL)
761 rc = vbsfUnlock(pClient, root, Handle, offset, length, flags);
762 else
763 rc = vbsfLock(pClient, root, Handle, offset, length, flags);
764
765 if (RT_SUCCESS(rc))
766 {
767 /* Update parameters.*/
768 /* none */
769 }
770 }
771 }
772 break;
773
774 /** List object content. */
775 case SHFL_FN_LIST:
776 {
777 Log(("SharedFolders host service: svcCall: SHFL_FN_LIST\n"));
778
779 /* Verify parameter count and types. */
780 if (cParms != SHFL_CPARMS_LIST)
781 {
782 rc = VERR_INVALID_PARAMETER;
783 }
784 else
785 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
786 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
787 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
788 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* cb */
789 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* pPath */
790 || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
791 || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* resumePoint */
792 || paParms[7].type != VBOX_HGCM_SVC_PARM_32BIT /* cFiles (out) */
793 )
794 {
795 rc = VERR_INVALID_PARAMETER;
796 }
797 else
798 {
799 /* Fetch parameters. */
800 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
801 SHFLHANDLE Handle = paParms[1].u.uint64;
802 uint32_t flags = paParms[2].u.uint32;
803 uint32_t length = paParms[3].u.uint32;
804 SHFLSTRING *pPath = (paParms[4].u.pointer.size == 0) ? 0 : (SHFLSTRING *)paParms[4].u.pointer.addr;
805 uint8_t *pBuffer = (uint8_t *)paParms[5].u.pointer.addr;
806 uint32_t resumePoint = paParms[6].u.uint32;
807 uint32_t cFiles = 0;
808
809 /* Verify parameters values. */
810 if ( (length < sizeof (SHFLDIRINFO))
811 || length > paParms[5].u.pointer.size
812 || !ShflStringIsValidOrNullIn(pPath, paParms[4].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))
813 )
814 {
815 rc = VERR_INVALID_PARAMETER;
816 }
817 else
818 {
819 if (pStatusLed)
820 {
821 Assert(pStatusLed->u32Magic == PDMLED_MAGIC);
822 pStatusLed->Asserted.s.fReading = pStatusLed->Actual.s.fReading = 1;
823 }
824
825 /* Execute the function. */
826 rc = vbsfDirList (pClient, root, Handle, pPath, flags, &length, pBuffer, &resumePoint, &cFiles);
827
828 if (pStatusLed)
829 pStatusLed->Actual.s.fReading = 0;
830
831 if (rc == VERR_NO_MORE_FILES && cFiles != 0)
832 rc = VINF_SUCCESS; /* Successfully return these files. */
833
834 if (RT_SUCCESS(rc))
835 {
836 /* Update parameters.*/
837 paParms[3].u.uint32 = length;
838 paParms[6].u.uint32 = resumePoint;
839 paParms[7].u.uint32 = cFiles;
840 }
841 else
842 {
843 paParms[3].u.uint32 = 0; /* nothing read */
844 paParms[6].u.uint32 = 0;
845 paParms[7].u.uint32 = cFiles;
846 }
847 }
848 }
849 break;
850 }
851
852 /* Read symlink destination */
853 case SHFL_FN_READLINK:
854 {
855 Log(("SharedFolders host service: svcCall: SHFL_FN_READLINK\n"));
856
857 /* Verify parameter count and types. */
858 if (cParms != SHFL_CPARMS_READLINK)
859 {
860 rc = VERR_INVALID_PARAMETER;
861 }
862 else
863 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
864 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* path */
865 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
866 )
867 {
868 rc = VERR_INVALID_PARAMETER;
869 }
870 else
871 {
872 /* Fetch parameters. */
873 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
874 SHFLSTRING *pPath = (SHFLSTRING *)paParms[1].u.pointer.addr;
875 uint32_t cbPath = paParms[1].u.pointer.size;
876 uint8_t *pBuffer = (uint8_t *)paParms[2].u.pointer.addr;
877 uint32_t cbBuffer = paParms[2].u.pointer.size;
878
879 /* Verify parameters values. */
880 if (!ShflStringIsValidOrNullIn(pPath, paParms[1].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)))
881 {
882 rc = VERR_INVALID_PARAMETER;
883 }
884 else
885 {
886 /* Execute the function. */
887 rc = vbsfReadLink (pClient, root, pPath, cbPath, pBuffer, cbBuffer);
888
889 if (RT_SUCCESS(rc))
890 {
891 /* Update parameters.*/
892 ; /* none */
893 }
894 }
895 }
896
897 break;
898 }
899
900 /* Legacy interface */
901 case SHFL_FN_MAP_FOLDER_OLD:
902 {
903 Log(("SharedFolders host service: svcCall: SHFL_FN_MAP_FOLDER_OLD\n"));
904
905 /* Verify parameter count and types. */
906 if (cParms != SHFL_CPARMS_MAP_FOLDER_OLD)
907 {
908 rc = VERR_INVALID_PARAMETER;
909 }
910 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* path */
911 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
912 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* delimiter */
913 )
914 {
915 rc = VERR_INVALID_PARAMETER;
916 }
917 else
918 {
919 /* Fetch parameters. */
920 PSHFLSTRING pszMapName = (PSHFLSTRING)paParms[0].u.pointer.addr;
921 SHFLROOT root = (SHFLROOT)paParms[1].u.uint32;
922 RTUTF16 delimiter = (RTUTF16)paParms[2].u.uint32;
923
924 /* Verify parameters values. */
925 if (!ShflStringIsValidIn(pszMapName, paParms[0].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)))
926 {
927 rc = VERR_INVALID_PARAMETER;
928 }
929 else
930 {
931 /* Execute the function. */
932 rc = vbsfMapFolder (pClient, pszMapName, delimiter, false, &root);
933
934 if (RT_SUCCESS(rc))
935 {
936 /* Update parameters.*/
937 paParms[1].u.uint32 = root;
938 }
939 }
940 }
941 break;
942 }
943
944 case SHFL_FN_MAP_FOLDER:
945 {
946 Log(("SharedFolders host service: svcCall: SHFL_FN_MAP_FOLDER\n"));
947 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
948 Log(("SharedFolders host service: request to map folder '%s'\n",
949 ((PSHFLSTRING)paParms[0].u.pointer.addr)->String.utf8));
950 else
951 Log(("SharedFolders host service: request to map folder '%ls'\n",
952 ((PSHFLSTRING)paParms[0].u.pointer.addr)->String.ucs2));
953
954 /* Verify parameter count and types. */
955 if (cParms != SHFL_CPARMS_MAP_FOLDER)
956 {
957 rc = VERR_INVALID_PARAMETER;
958 }
959 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* path */
960 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
961 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* delimiter */
962 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* fCaseSensitive */
963 )
964 {
965 rc = VERR_INVALID_PARAMETER;
966 }
967 else
968 {
969 /* Fetch parameters. */
970 PSHFLSTRING pszMapName = (PSHFLSTRING)paParms[0].u.pointer.addr;
971 SHFLROOT root = (SHFLROOT)paParms[1].u.uint32;
972 RTUTF16 delimiter = (RTUTF16)paParms[2].u.uint32;
973 bool fCaseSensitive = !!paParms[3].u.uint32;
974
975 /* Verify parameters values. */
976 if (ShflStringIsValidIn(pszMapName, paParms[0].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)))
977 {
978 rc = VINF_SUCCESS;
979 }
980 else
981 {
982 rc = VERR_INVALID_PARAMETER;
983
984 /* Fudge for windows GAs getting the length wrong by one char. */
985 if ( !(pClient->fu32Flags & SHFL_CF_UTF8)
986 && paParms[0].u.pointer.size >= sizeof(SHFLSTRING)
987 && pszMapName->u16Length >= 2
988 && pszMapName->String.ucs2[pszMapName->u16Length / 2 - 1] == 0x0000)
989 {
990 pszMapName->u16Length -= 2;
991 if (ShflStringIsValidIn(pszMapName, paParms[0].u.pointer.size, false /*fUtf8Not16*/))
992 rc = VINF_SUCCESS;
993 else
994 pszMapName->u16Length += 2;
995 }
996 }
997
998 /* Execute the function. */
999 if (RT_SUCCESS(rc))
1000 rc = vbsfMapFolder (pClient, pszMapName, delimiter, fCaseSensitive, &root);
1001
1002 if (RT_SUCCESS(rc))
1003 {
1004 /* Update parameters.*/
1005 paParms[1].u.uint32 = root;
1006 }
1007 }
1008 Log(("SharedFolders host service: map operation result %Rrc\n", rc));
1009 if (RT_SUCCESS(rc))
1010 Log(("SharedFolders host service: mapped to handle %d\n", paParms[1].u.uint32));
1011 break;
1012 }
1013
1014 case SHFL_FN_UNMAP_FOLDER:
1015 {
1016 Log(("SharedFolders host service: svcCall: SHFL_FN_UNMAP_FOLDER\n"));
1017 Log(("SharedFolders host service: request to unmap folder handle %u\n",
1018 paParms[0].u.uint32));
1019
1020 /* Verify parameter count and types. */
1021 if (cParms != SHFL_CPARMS_UNMAP_FOLDER)
1022 {
1023 rc = VERR_INVALID_PARAMETER;
1024 }
1025 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
1026 )
1027 {
1028 rc = VERR_INVALID_PARAMETER;
1029 }
1030 else
1031 {
1032 /* Fetch parameters. */
1033 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
1034
1035 /* Execute the function. */
1036 rc = vbsfUnmapFolder (pClient, root);
1037
1038 if (RT_SUCCESS(rc))
1039 {
1040 /* Update parameters.*/
1041 /* nothing */
1042 }
1043 }
1044 Log(("SharedFolders host service: unmap operation result %Rrc\n", rc));
1045 break;
1046 }
1047
1048 /** Query/set object information. */
1049 case SHFL_FN_INFORMATION:
1050 {
1051 Log(("SharedFolders host service: svcCall: SHFL_FN_INFORMATION\n"));
1052
1053 /* Verify parameter count and types. */
1054 if (cParms != SHFL_CPARMS_INFORMATION)
1055 {
1056 rc = VERR_INVALID_PARAMETER;
1057 }
1058 else
1059 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
1060 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
1061 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
1062 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* cb */
1063 || paParms[4].type != VBOX_HGCM_SVC_PARM_PTR /* buffer */
1064 )
1065 {
1066 rc = VERR_INVALID_PARAMETER;
1067 }
1068 else
1069 {
1070 /* Fetch parameters. */
1071 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
1072 SHFLHANDLE Handle = paParms[1].u.uint64;
1073 uint32_t flags = paParms[2].u.uint32;
1074 uint32_t length = paParms[3].u.uint32;
1075 uint8_t *pBuffer = (uint8_t *)paParms[4].u.pointer.addr;
1076
1077 /* Verify parameters values. */
1078 if (length > paParms[4].u.pointer.size)
1079 {
1080 rc = VERR_INVALID_PARAMETER;
1081 }
1082 else
1083 {
1084 /* Execute the function. */
1085 if (flags & SHFL_INFO_SET)
1086 rc = vbsfSetFSInfo (pClient, root, Handle, flags, &length, pBuffer);
1087 else /* SHFL_INFO_GET */
1088 rc = vbsfQueryFSInfo (pClient, root, Handle, flags, &length, pBuffer);
1089
1090 if (RT_SUCCESS(rc))
1091 {
1092 /* Update parameters.*/
1093 paParms[3].u.uint32 = length;
1094 }
1095 else
1096 {
1097 paParms[3].u.uint32 = 0; /* nothing read */
1098 }
1099 }
1100 }
1101 break;
1102 }
1103
1104 /** Remove or rename object */
1105 case SHFL_FN_REMOVE:
1106 {
1107 Log(("SharedFolders host service: svcCall: SHFL_FN_REMOVE\n"));
1108
1109 /* Verify parameter count and types. */
1110 if (cParms != SHFL_CPARMS_REMOVE)
1111 {
1112 rc = VERR_INVALID_PARAMETER;
1113 }
1114 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
1115 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* path */
1116 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
1117 )
1118 {
1119 rc = VERR_INVALID_PARAMETER;
1120 }
1121 else
1122 {
1123 /* Fetch parameters. */
1124 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
1125 SHFLSTRING *pPath = (SHFLSTRING *)paParms[1].u.pointer.addr;
1126 uint32_t cbPath = paParms[1].u.pointer.size;
1127 uint32_t flags = paParms[2].u.uint32;
1128
1129 /* Verify parameters values. */
1130 if (!ShflStringIsValidIn(pPath, cbPath, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8)))
1131 {
1132 rc = VERR_INVALID_PARAMETER;
1133 }
1134 else
1135 {
1136 /* Execute the function. */
1137 rc = vbsfRemove (pClient, root, pPath, cbPath, flags);
1138 if (RT_SUCCESS(rc))
1139 {
1140 /* Update parameters.*/
1141 ; /* none */
1142 }
1143 }
1144 }
1145 break;
1146 }
1147
1148 case SHFL_FN_RENAME:
1149 {
1150 Log(("SharedFolders host service: svcCall: SHFL_FN_RENAME\n"));
1151
1152 /* Verify parameter count and types. */
1153 if (cParms != SHFL_CPARMS_RENAME)
1154 {
1155 rc = VERR_INVALID_PARAMETER;
1156 }
1157 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
1158 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* src */
1159 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* dest */
1160 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */
1161 )
1162 {
1163 rc = VERR_INVALID_PARAMETER;
1164 }
1165 else
1166 {
1167 /* Fetch parameters. */
1168 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
1169 SHFLSTRING *pSrc = (SHFLSTRING *)paParms[1].u.pointer.addr;
1170 SHFLSTRING *pDest = (SHFLSTRING *)paParms[2].u.pointer.addr;
1171 uint32_t flags = paParms[3].u.uint32;
1172
1173 /* Verify parameters values. */
1174 if ( !ShflStringIsValidIn(pSrc, paParms[1].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))
1175 || !ShflStringIsValidIn(pDest, paParms[2].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))
1176 )
1177 {
1178 rc = VERR_INVALID_PARAMETER;
1179 }
1180 else
1181 {
1182 /* Execute the function. */
1183 rc = vbsfRename (pClient, root, pSrc, pDest, flags);
1184 if (RT_SUCCESS(rc))
1185 {
1186 /* Update parameters.*/
1187 ; /* none */
1188 }
1189 }
1190 }
1191 break;
1192 }
1193
1194 case SHFL_FN_FLUSH:
1195 {
1196 Log(("SharedFolders host service: svcCall: SHFL_FN_FLUSH\n"));
1197
1198 /* Verify parameter count and types. */
1199 if (cParms != SHFL_CPARMS_FLUSH)
1200 {
1201 rc = VERR_INVALID_PARAMETER;
1202 }
1203 else
1204 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
1205 || paParms[1].type != VBOX_HGCM_SVC_PARM_64BIT /* handle */
1206 )
1207 {
1208 rc = VERR_INVALID_PARAMETER;
1209 }
1210 else
1211 {
1212 /* Fetch parameters. */
1213 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
1214 SHFLHANDLE Handle = paParms[1].u.uint64;
1215
1216 /* Verify parameters values. */
1217 if (Handle == SHFL_HANDLE_ROOT)
1218 {
1219 rc = VERR_INVALID_PARAMETER;
1220 }
1221 else
1222 if (Handle == SHFL_HANDLE_NIL)
1223 {
1224 AssertMsgFailed(("Invalid handle!\n"));
1225 rc = VERR_INVALID_HANDLE;
1226 }
1227 else
1228 {
1229 /* Execute the function. */
1230
1231 rc = vbsfFlush (pClient, root, Handle);
1232
1233 if (RT_SUCCESS(rc))
1234 {
1235 /* Nothing to do */
1236 }
1237 }
1238 }
1239 } break;
1240
1241 case SHFL_FN_SET_UTF8:
1242 {
1243 pClient->fu32Flags |= SHFL_CF_UTF8;
1244 rc = VINF_SUCCESS;
1245 break;
1246 }
1247
1248 case SHFL_FN_SYMLINK:
1249 {
1250 Log(("SharedFolders host service: svnCall: SHFL_FN_SYMLINK\n"));
1251 /* Verify parameter count and types. */
1252 if (cParms != SHFL_CPARMS_SYMLINK)
1253 {
1254 rc = VERR_INVALID_PARAMETER;
1255 }
1256 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* root */
1257 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* newPath */
1258 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* oldPath */
1259 || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /* info */
1260 )
1261 {
1262 rc = VERR_INVALID_PARAMETER;
1263 }
1264 else
1265 {
1266 /* Fetch parameters. */
1267 SHFLROOT root = (SHFLROOT)paParms[0].u.uint32;
1268 SHFLSTRING *pNewPath = (SHFLSTRING *)paParms[1].u.pointer.addr;
1269 SHFLSTRING *pOldPath = (SHFLSTRING *)paParms[2].u.pointer.addr;
1270 SHFLFSOBJINFO *pInfo = (SHFLFSOBJINFO *)paParms[3].u.pointer.addr;
1271 uint32_t cbInfo = paParms[3].u.pointer.size;
1272
1273 /* Verify parameters values. */
1274 if ( !ShflStringIsValidIn(pNewPath, paParms[1].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))
1275 || !ShflStringIsValidIn(pOldPath, paParms[2].u.pointer.size, RT_BOOL(pClient->fu32Flags & SHFL_CF_UTF8))
1276 || (cbInfo != sizeof(SHFLFSOBJINFO))
1277 )
1278 {
1279 rc = VERR_INVALID_PARAMETER;
1280 }
1281 else
1282 {
1283 /* Execute the function. */
1284 rc = vbsfSymlink (pClient, root, pNewPath, pOldPath, pInfo);
1285 if (RT_SUCCESS(rc))
1286 {
1287 /* Update parameters.*/
1288 ; /* none */
1289 }
1290 }
1291 }
1292 }
1293 break;
1294
1295 case SHFL_FN_SET_SYMLINKS:
1296 {
1297 pClient->fu32Flags |= SHFL_CF_SYMLINKS;
1298 rc = VINF_SUCCESS;
1299 break;
1300 }
1301
1302 case SHFL_FN_QUERY_MAP_INFO:
1303 {
1304 Log(("SharedFolders host service: svnCall: SHFL_FN_QUERY_MAP_INFO\n"));
1305
1306 /* Validate input: */
1307 rc = VERR_INVALID_PARAMETER;
1308 ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_QUERY_MAP_INFO);
1309 ASSERT_GUEST_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT); /* root */
1310 ASSERT_GUEST_BREAK(paParms[1].type == VBOX_HGCM_SVC_PARM_PTR); /* name */
1311 PSHFLSTRING pNameBuf = (PSHFLSTRING)paParms[1].u.pointer.addr;
1312 ASSERT_GUEST_BREAK(ShflStringIsValidOut(pNameBuf, paParms[1].u.pointer.size));
1313 ASSERT_GUEST_BREAK(paParms[2].type == VBOX_HGCM_SVC_PARM_PTR); /* mountPoint */
1314 PSHFLSTRING pMntPtBuf = (PSHFLSTRING)paParms[2].u.pointer.addr;
1315 ASSERT_GUEST_BREAK(ShflStringIsValidOut(pMntPtBuf, paParms[2].u.pointer.size));
1316 ASSERT_GUEST_BREAK(paParms[3].type == VBOX_HGCM_SVC_PARM_64BIT); /* flags */
1317 ASSERT_GUEST_BREAK(!(paParms[3].u.uint64 & ~(SHFL_MIQF_DRIVE_LETTER | SHFL_MIQF_PATH))); /* flags */
1318 ASSERT_GUEST_BREAK(paParms[4].type == VBOX_HGCM_SVC_PARM_32BIT); /* version */
1319
1320 /* Execute the function: */
1321 rc = vbsfMappingsQueryInfo(pClient, paParms[0].u.uint32, pNameBuf, pMntPtBuf,
1322 &paParms[3].u.uint64, &paParms[4].u.uint32);
1323 break;
1324 }
1325
1326 case SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES:
1327 {
1328 Log(("SharedFolders host service: svnCall: SHFL_FN_WAIT_FOR_CHANGES\n"));
1329
1330 /* Validate input: */
1331 rc = VERR_INVALID_PARAMETER;
1332 ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_WAIT_FOR_MAPPINGS_CHANGES);
1333 ASSERT_GUEST_BREAK(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT); /* uFolderMappingsVersion */
1334
1335 /* Execute the function: */
1336 rc = vbsfMappingsWaitForChanges(pClient, callHandle, paParms, g_pHelpers->pfnIsCallRestored(callHandle));
1337 fAsynchronousProcessing = rc == VINF_HGCM_ASYNC_EXECUTE;
1338 break;
1339 }
1340
1341 case SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS:
1342 {
1343 Log(("SharedFolders host service: svnCall: SHFL_FN_CANCEL_WAIT_FOR_CHANGES\n"));
1344
1345 /* Validate input: */
1346 rc = VERR_INVALID_PARAMETER;
1347 ASSERT_GUEST_BREAK(cParms == SHFL_CPARMS_CANCEL_MAPPINGS_CHANGES_WAITS);
1348
1349 /* Execute the function: */
1350 rc = vbsfMappingsCancelChangesWaits(pClient);
1351 break;
1352 }
1353
1354 default:
1355 {
1356 rc = VERR_NOT_IMPLEMENTED;
1357 break;
1358 }
1359 }
1360
1361 LogFlow(("SharedFolders host service: svcCall: rc=%Rrc\n", rc));
1362
1363 if ( !fAsynchronousProcessing
1364 || RT_FAILURE (rc))
1365 {
1366 /* Complete the operation if it was unsuccessful or
1367 * it was processed synchronously.
1368 */
1369 g_pHelpers->pfnCallComplete (callHandle, rc);
1370 }
1371
1372 LogFlow(("\n")); /* Add a new line to differentiate between calls more easily. */
1373}
1374
1375/*
1376 * We differentiate between a function handler for the guest (svcCall) and one
1377 * for the host. The guest is not allowed to add or remove mappings for obvious
1378 * security reasons.
1379 */
1380static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
1381{
1382 int rc = VINF_SUCCESS;
1383
1384 Log(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
1385
1386#ifdef DEBUG
1387 uint32_t i;
1388
1389 for (i = 0; i < cParms; i++)
1390 {
1391 /** @todo parameters other than 32 bit */
1392 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
1393 }
1394#endif
1395
1396 switch (u32Function)
1397 {
1398 case SHFL_FN_ADD_MAPPING:
1399 {
1400 Log(("SharedFolders host service: svcCall: SHFL_FN_ADD_MAPPING\n"));
1401 LogRel(("SharedFolders host service: Adding host mapping\n"));
1402 /* Verify parameter count and types. */
1403 if ( (cParms != SHFL_CPARMS_ADD_MAPPING)
1404 )
1405 {
1406 rc = VERR_INVALID_PARAMETER;
1407 }
1408 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* host folder path */
1409 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* map name */
1410 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* fFlags */
1411 || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /* auto mount point */
1412 )
1413 {
1414 rc = VERR_INVALID_PARAMETER;
1415 }
1416 else
1417 {
1418 /* Fetch parameters. */
1419 SHFLSTRING *pHostPath = (SHFLSTRING *)paParms[0].u.pointer.addr;
1420 SHFLSTRING *pMapName = (SHFLSTRING *)paParms[1].u.pointer.addr;
1421 uint32_t fFlags = paParms[2].u.uint32;
1422 SHFLSTRING *pAutoMountPoint = (SHFLSTRING *)paParms[3].u.pointer.addr;
1423
1424 /* Verify parameters values. */
1425 if ( !ShflStringIsValidIn(pHostPath, paParms[0].u.pointer.size, false /*fUtf8Not16*/)
1426 || !ShflStringIsValidIn(pMapName, paParms[1].u.pointer.size, false /*fUtf8Not16*/)
1427 || !ShflStringIsValidIn(pAutoMountPoint, paParms[3].u.pointer.size, false /*fUtf8Not16*/)
1428 )
1429 {
1430 rc = VERR_INVALID_PARAMETER;
1431 }
1432 else
1433 {
1434 LogRel((" Host path '%ls', map name '%ls', %s, automount=%s, automntpnt=%s, create_symlinks=%s, missing=%s\n",
1435 pHostPath->String.utf16, pMapName->String.utf16,
1436 RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_WRITABLE) ? "writable" : "read-only",
1437 RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_AUTOMOUNT) ? "true" : "false",
1438 pAutoMountPoint->String.utf16,
1439 RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_CREATE_SYMLINKS) ? "true" : "false",
1440 RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_MISSING) ? "true" : "false"));
1441
1442 char *pszHostPath;
1443 rc = RTUtf16ToUtf8(pHostPath->String.ucs2, &pszHostPath);
1444 if (RT_SUCCESS(rc))
1445 {
1446 /* Execute the function. */
1447 rc = vbsfMappingsAdd(pszHostPath, pMapName,
1448 RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_WRITABLE),
1449 RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_AUTOMOUNT),
1450 pAutoMountPoint,
1451 RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_CREATE_SYMLINKS),
1452 RT_BOOL(fFlags & SHFL_ADD_MAPPING_F_MISSING),
1453 /* fPlaceholder = */ false);
1454 if (RT_SUCCESS(rc))
1455 {
1456 /* Update parameters.*/
1457 ; /* none */
1458 }
1459 RTStrFree(pszHostPath);
1460 }
1461 }
1462 }
1463 if (RT_FAILURE(rc))
1464 LogRel(("SharedFolders host service: Adding host mapping failed with rc=%Rrc\n", rc));
1465 break;
1466 }
1467
1468 case SHFL_FN_REMOVE_MAPPING:
1469 {
1470 Log(("SharedFolders host service: svcCall: SHFL_FN_REMOVE_MAPPING\n"));
1471 LogRel(("SharedFolders host service: Removing host mapping '%ls'\n",
1472 ((SHFLSTRING *)paParms[0].u.pointer.addr)->String.ucs2));
1473
1474 /* Verify parameter count and types. */
1475 if (cParms != SHFL_CPARMS_REMOVE_MAPPING)
1476 {
1477 rc = VERR_INVALID_PARAMETER;
1478 }
1479 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* folder name */
1480 )
1481 {
1482 rc = VERR_INVALID_PARAMETER;
1483 }
1484 else
1485 {
1486 /* Fetch parameters. */
1487 SHFLSTRING *pString = (SHFLSTRING *)paParms[0].u.pointer.addr;
1488
1489 /* Verify parameters values. */
1490 if (!ShflStringIsValidIn(pString, paParms[0].u.pointer.size, false /*fUtf8Not16*/))
1491 {
1492 rc = VERR_INVALID_PARAMETER;
1493 }
1494 else
1495 {
1496 /* Execute the function. */
1497 rc = vbsfMappingsRemove (pString);
1498
1499 if (RT_SUCCESS(rc))
1500 {
1501 /* Update parameters.*/
1502 ; /* none */
1503 }
1504 }
1505 }
1506 if (RT_FAILURE(rc))
1507 LogRel(("SharedFolders host service: Removing host mapping failed with rc=%Rrc\n", rc));
1508 break;
1509 }
1510
1511 case SHFL_FN_SET_STATUS_LED:
1512 {
1513 Log(("SharedFolders host service: svcCall: SHFL_FN_SET_STATUS_LED\n"));
1514
1515 /* Verify parameter count and types. */
1516 if (cParms != SHFL_CPARMS_SET_STATUS_LED)
1517 {
1518 rc = VERR_INVALID_PARAMETER;
1519 }
1520 else if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* folder name */
1521 )
1522 {
1523 rc = VERR_INVALID_PARAMETER;
1524 }
1525 else
1526 {
1527 /* Fetch parameters. */
1528 PPDMLED pLed = (PPDMLED)paParms[0].u.pointer.addr;
1529 uint32_t cbLed = paParms[0].u.pointer.size;
1530
1531 /* Verify parameters values. */
1532 if ( (cbLed != sizeof (PDMLED))
1533 )
1534 {
1535 rc = VERR_INVALID_PARAMETER;
1536 }
1537 else
1538 {
1539 /* Execute the function. */
1540 pStatusLed = pLed;
1541 rc = VINF_SUCCESS;
1542 }
1543 }
1544 break;
1545 }
1546
1547 default:
1548 rc = VERR_NOT_IMPLEMENTED;
1549 break;
1550 }
1551
1552 LogFlow(("SharedFolders host service: svcHostCall ended with rc=%Rrc\n", rc));
1553 return rc;
1554}
1555
1556extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
1557{
1558 int rc = VINF_SUCCESS;
1559
1560 Log(("SharedFolders host service: VBoxHGCMSvcLoad: ptable = %p\n", ptable));
1561
1562 if (!VALID_PTR(ptable))
1563 {
1564 LogRelFunc(("SharedFolders host service: Bad value of ptable (%p)\n", ptable));
1565 rc = VERR_INVALID_PARAMETER;
1566 }
1567 else
1568 {
1569 Log(("SharedFolders host service: VBoxHGCMSvcLoad: ptable->cbSize = %u, ptable->u32Version = 0x%08X\n",
1570 ptable->cbSize, ptable->u32Version));
1571
1572 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
1573 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
1574 {
1575 LogRelFunc(("SharedFolders host service: Version mismatch while loading: ptable->cbSize = %u (should be %u), ptable->u32Version = 0x%08X (should be 0x%08X)\n",
1576 ptable->cbSize, sizeof (VBOXHGCMSVCFNTABLE), ptable->u32Version, VBOX_HGCM_SVC_VERSION));
1577 rc = VERR_VERSION_MISMATCH;
1578 }
1579 else
1580 {
1581 g_pHelpers = ptable->pHelpers;
1582
1583 ptable->cbClient = sizeof (SHFLCLIENTDATA);
1584
1585 ptable->pfnUnload = svcUnload;
1586 ptable->pfnConnect = svcConnect;
1587 ptable->pfnDisconnect = svcDisconnect;
1588 ptable->pfnCall = svcCall;
1589 ptable->pfnHostCall = svcHostCall;
1590 ptable->pfnSaveState = svcSaveState;
1591 ptable->pfnLoadState = svcLoadState;
1592 ptable->pvService = NULL;
1593 }
1594
1595 /* Init handle table */
1596 rc = vbsfInitHandleTable();
1597 AssertRC(rc);
1598
1599 vbsfMappingInit();
1600 }
1601
1602 return rc;
1603}
1604
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