VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedFolders/mappings.cpp@ 66012

Last change on this file since 66012 was 65998, checked in by vboxsync, 8 years ago

SharedFolders: Do RTAbsPath on folder roots, don't double convert to UTF-8 when calling RTFsQueryProperties, testcase workarounds for new absolute path handling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.9 KB
Line 
1/** @file
2 * Shared Folders: Mappings support.
3 */
4
5/*
6 * Copyright (C) 2006-2016 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#ifdef UNITTEST
18# include "testcase/tstSharedFolderService.h"
19#endif
20
21#include "mappings.h"
22#include <iprt/alloc.h>
23#include <iprt/assert.h>
24#include <iprt/path.h>
25#include <iprt/string.h>
26
27#ifdef UNITTEST
28# include "teststubs.h"
29#endif
30
31/* Shared folders order in the saved state and in the FolderMapping can differ.
32 * So a translation array of root handle is needed.
33 */
34
35static MAPPING FolderMapping[SHFL_MAX_MAPPINGS];
36static SHFLROOT aIndexFromRoot[SHFL_MAX_MAPPINGS];
37
38void vbsfMappingInit(void)
39{
40 unsigned root;
41
42 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++)
43 {
44 aIndexFromRoot[root] = SHFL_ROOT_NIL;
45 }
46}
47
48int vbsfMappingLoaded(const PMAPPING pLoadedMapping, SHFLROOT root)
49{
50 /* Mapping loaded from the saved state with the index. Which means
51 * the guest uses the iMapping as root handle for this folder.
52 * Check whether there is the same mapping in FolderMapping and
53 * update the aIndexFromRoot.
54 *
55 * Also update the mapping properties, which were lost: cMappings.
56 */
57 if (root >= SHFL_MAX_MAPPINGS)
58 {
59 return VERR_INVALID_PARAMETER;
60 }
61
62 SHFLROOT i;
63 for (i = 0; i < RT_ELEMENTS(FolderMapping); i++)
64 {
65 MAPPING *pMapping = &FolderMapping[i];
66
67 /* Equal? */
68 if ( pLoadedMapping->fValid == pMapping->fValid
69 && ShflStringSizeOfBuffer(pLoadedMapping->pMapName) == ShflStringSizeOfBuffer(pMapping->pMapName)
70 && memcmp(pLoadedMapping->pMapName, pMapping->pMapName, ShflStringSizeOfBuffer(pMapping->pMapName)) == 0)
71 {
72 /* Actual index is i. */
73 aIndexFromRoot[root] = i;
74
75 /* Update the mapping properties. */
76 pMapping->cMappings = pLoadedMapping->cMappings;
77
78 return VINF_SUCCESS;
79 }
80 }
81
82 /* No corresponding mapping on the host but the guest still uses it.
83 * Add a 'placeholder' mapping.
84 */
85 LogRel2(("SharedFolders: mapping a placeholder for '%ls' -> '%s'\n",
86 pLoadedMapping->pMapName->String.ucs2, pLoadedMapping->pszFolderName));
87 return vbsfMappingsAdd(pLoadedMapping->pszFolderName, pLoadedMapping->pMapName,
88 pLoadedMapping->fWritable, pLoadedMapping->fAutoMount,
89 pLoadedMapping->fSymlinksCreate, /* fMissing = */ true, /* fPlaceholder = */ true);
90}
91
92MAPPING *vbsfMappingGetByRoot(SHFLROOT root)
93{
94 if (root < RT_ELEMENTS(aIndexFromRoot))
95 {
96 SHFLROOT iMapping = aIndexFromRoot[root];
97
98 if ( iMapping != SHFL_ROOT_NIL
99 && iMapping < RT_ELEMENTS(FolderMapping))
100 {
101 return &FolderMapping[iMapping];
102 }
103 }
104
105 return NULL;
106}
107
108static SHFLROOT vbsfMappingGetRootFromIndex(SHFLROOT iMapping)
109{
110 unsigned root;
111
112 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++)
113 {
114 if (iMapping == aIndexFromRoot[root])
115 {
116 return root;
117 }
118 }
119
120 return SHFL_ROOT_NIL;
121}
122
123static MAPPING *vbsfMappingGetByName (PRTUTF16 pwszName, SHFLROOT *pRoot)
124{
125 unsigned i;
126
127 for (i=0; i<SHFL_MAX_MAPPINGS; i++)
128 {
129 if (FolderMapping[i].fValid == true)
130 {
131 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pwszName))
132 {
133 SHFLROOT root = vbsfMappingGetRootFromIndex(i);
134
135 if (root != SHFL_ROOT_NIL)
136 {
137 if (pRoot)
138 {
139 *pRoot = root;
140 }
141 return &FolderMapping[i];
142 }
143 else
144 {
145 AssertFailed();
146 }
147 }
148 }
149 }
150
151 return NULL;
152}
153
154static void vbsfRootHandleAdd(SHFLROOT iMapping)
155{
156 unsigned root;
157
158 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++)
159 {
160 if (aIndexFromRoot[root] == SHFL_ROOT_NIL)
161 {
162 aIndexFromRoot[root] = iMapping;
163 return;
164 }
165 }
166
167 AssertFailed();
168}
169
170static void vbsfRootHandleRemove(SHFLROOT iMapping)
171{
172 unsigned root;
173
174 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++)
175 {
176 if (aIndexFromRoot[root] == iMapping)
177 {
178 aIndexFromRoot[root] = SHFL_ROOT_NIL;
179 return;
180 }
181 }
182
183 AssertFailed();
184}
185
186
187
188#ifdef UNITTEST
189/** Unit test the SHFL_FN_ADD_MAPPING API. Located here as a form of API
190 * documentation. */
191void testMappingsAdd(RTTEST hTest)
192{
193 /* If the number or types of parameters are wrong the API should fail. */
194 testMappingsAddBadParameters(hTest);
195 /* Add tests as required... */
196}
197#endif
198/*
199 * We are always executed from one specific HGCM thread. So thread safe.
200 */
201int vbsfMappingsAdd(const char *pszFolderName, PSHFLSTRING pMapName,
202 bool fWritable, bool fAutoMount, bool fSymlinksCreate, bool fMissing, bool fPlaceholder)
203{
204 unsigned i;
205
206 Assert(pszFolderName && pMapName);
207
208 Log(("vbsfMappingsAdd %ls\n", pMapName->String.ucs2));
209
210 /* check for duplicates */
211 for (i=0; i<SHFL_MAX_MAPPINGS; i++)
212 {
213 if (FolderMapping[i].fValid == true)
214 {
215 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2))
216 {
217 AssertMsgFailed(("vbsfMappingsAdd: %ls mapping already exists!!\n", pMapName->String.ucs2));
218 return VERR_ALREADY_EXISTS;
219 }
220 }
221 }
222
223 for (i=0; i<SHFL_MAX_MAPPINGS; i++)
224 {
225 if (FolderMapping[i].fValid == false)
226 {
227 /* Make sure the folder name is an absolute path, otherwise we're
228 likely to get into trouble with buffer sizes in vbsfPathGuestToHost. */
229 char szAbsFolderName[RTPATH_MAX];
230 int rc = RTPathAbs(pszFolderName, szAbsFolderName, sizeof(szAbsFolderName));
231 AssertRCReturn(rc, rc);
232
233 FolderMapping[i].pszFolderName = RTStrDup(szAbsFolderName);
234 if (!FolderMapping[i].pszFolderName)
235 {
236 return VERR_NO_MEMORY;
237 }
238
239 FolderMapping[i].pMapName = (PSHFLSTRING)RTMemAlloc(ShflStringSizeOfBuffer(pMapName));
240 if (!FolderMapping[i].pMapName)
241 {
242 RTStrFree(FolderMapping[i].pszFolderName);
243 AssertFailed();
244 return VERR_NO_MEMORY;
245 }
246
247 FolderMapping[i].pMapName->u16Length = pMapName->u16Length;
248 FolderMapping[i].pMapName->u16Size = pMapName->u16Size;
249 memcpy(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2, pMapName->u16Size);
250
251 FolderMapping[i].fValid = true;
252 FolderMapping[i].cMappings = 0;
253 FolderMapping[i].fWritable = fWritable;
254 FolderMapping[i].fAutoMount = fAutoMount;
255 FolderMapping[i].fSymlinksCreate = fSymlinksCreate;
256 FolderMapping[i].fMissing = fMissing;
257 FolderMapping[i].fPlaceholder = fPlaceholder;
258
259 /* Check if the host file system is case sensitive */
260 RTFSPROPERTIES prop;
261 prop.fCaseSensitive = false; /* Shut up MSC. */
262 rc = RTFsQueryProperties(FolderMapping[i].pszFolderName, &prop);
263 AssertRC(rc);
264 FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false;
265 vbsfRootHandleAdd(i);
266 break;
267 }
268 }
269 if (i == SHFL_MAX_MAPPINGS)
270 {
271 AssertLogRelMsgFailed(("vbsfMappingsAdd: no more room to add mapping %s to %ls!!\n", pszFolderName, pMapName->String.ucs2));
272 return VERR_TOO_MUCH_DATA;
273 }
274
275 Log(("vbsfMappingsAdd: added mapping %s to %ls\n", pszFolderName, pMapName->String.ucs2));
276 return VINF_SUCCESS;
277}
278
279#ifdef UNITTEST
280/** Unit test the SHFL_FN_REMOVE_MAPPING API. Located here as a form of API
281 * documentation. */
282void testMappingsRemove(RTTEST hTest)
283{
284 /* If the number or types of parameters are wrong the API should fail. */
285 testMappingsRemoveBadParameters(hTest);
286 /* Add tests as required... */
287}
288#endif
289int vbsfMappingsRemove(PSHFLSTRING pMapName)
290{
291 unsigned i;
292
293 Assert(pMapName);
294
295 Log(("vbsfMappingsRemove %ls\n", pMapName->String.ucs2));
296 for (i=0; i<SHFL_MAX_MAPPINGS; i++)
297 {
298 if (FolderMapping[i].fValid == true)
299 {
300 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2))
301 {
302 if (FolderMapping[i].cMappings != 0)
303 {
304 LogRel2(("SharedFolders: removing '%ls' -> '%s', which is still used by the guest\n",
305 pMapName->String.ucs2, FolderMapping[i].pszFolderName));
306 FolderMapping[i].fMissing = true;
307 FolderMapping[i].fPlaceholder = true;
308 return VINF_PERMISSION_DENIED;
309 }
310
311 /* pMapName can be the same as FolderMapping[i].pMapName,
312 * log it before deallocating the memory.
313 */
314 Log(("vbsfMappingsRemove: mapping %ls removed\n", pMapName->String.ucs2));
315
316 RTStrFree(FolderMapping[i].pszFolderName);
317 RTMemFree(FolderMapping[i].pMapName);
318 FolderMapping[i].pszFolderName = NULL;
319 FolderMapping[i].pMapName = NULL;
320 FolderMapping[i].fValid = false;
321 vbsfRootHandleRemove(i);
322 return VINF_SUCCESS;
323 }
324 }
325 }
326
327 AssertMsgFailed(("vbsfMappingsRemove: mapping %ls not found!!!!\n", pMapName->String.ucs2));
328 return VERR_FILE_NOT_FOUND;
329}
330
331const char* vbsfMappingsQueryHostRoot(SHFLROOT root)
332{
333 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
334 AssertReturn(pFolderMapping, NULL);
335 if (pFolderMapping->fMissing)
336 return NULL;
337 return pFolderMapping->pszFolderName;
338}
339
340int vbsfMappingsQueryHostRootEx(SHFLROOT hRoot, const char **ppszRoot, uint32_t *pcbRootLen)
341{
342 MAPPING *pFolderMapping = vbsfMappingGetByRoot(hRoot);
343 AssertReturn(pFolderMapping, VERR_INVALID_PARAMETER);
344 if (pFolderMapping->fMissing)
345 return VERR_NOT_FOUND;
346 if ( pFolderMapping->pszFolderName == NULL
347 || pFolderMapping->pszFolderName[0] == 0)
348 return VERR_NOT_FOUND;
349 *ppszRoot = pFolderMapping->pszFolderName;
350 *pcbRootLen = (uint32_t)strlen(pFolderMapping->pszFolderName);
351 return VINF_SUCCESS;
352}
353
354bool vbsfIsGuestMappingCaseSensitive(SHFLROOT root)
355{
356 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
357 AssertReturn(pFolderMapping, false);
358 return pFolderMapping->fGuestCaseSensitive;
359}
360
361bool vbsfIsHostMappingCaseSensitive(SHFLROOT root)
362{
363 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
364 AssertReturn(pFolderMapping, false);
365 return pFolderMapping->fHostCaseSensitive;
366}
367
368#ifdef UNITTEST
369/** Unit test the SHFL_FN_QUERY_MAPPINGS API. Located here as a form of API
370 * documentation (or should it better be inline in include/VBox/shflsvc.h?) */
371void testMappingsQuery(RTTEST hTest)
372{
373 /* The API should return all mappings if we provide enough buffers. */
374 testMappingsQuerySimple(hTest);
375 /* If we provide too few buffers that should be signalled correctly. */
376 testMappingsQueryTooFewBuffers(hTest);
377 /* The SHFL_MF_AUTOMOUNT flag means return only auto-mounted mappings. */
378 testMappingsQueryAutoMount(hTest);
379 /* The mappings return array must have numberOfMappings entries. */
380 testMappingsQueryArrayWrongSize(hTest);
381}
382#endif
383/**
384 * Note: If pMappings / *pcMappings is smaller than the actual amount of mappings
385 * that *could* have been returned *pcMappings contains the required buffer size
386 * so that the caller can retry the operation if wanted.
387 */
388int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, PSHFLMAPPING pMappings, uint32_t *pcMappings)
389{
390 int rc = VINF_SUCCESS;
391
392 uint32_t cMappings = 0; /* Will contain actual valid mappings. */
393 uint32_t idx = 0; /* Current index in mappings buffer. */
394
395 LogFlow(("vbsfMappingsQuery: pClient = %p, pMappings = %p, pcMappings = %p, *pcMappings = %d\n",
396 pClient, pMappings, pcMappings, *pcMappings));
397
398 for (uint32_t i = 0; i < SHFL_MAX_MAPPINGS; i++)
399 {
400 MAPPING *pFolderMapping = vbsfMappingGetByRoot(i);
401 if ( pFolderMapping != NULL
402 && pFolderMapping->fValid == true)
403 {
404 if (idx < *pcMappings)
405 {
406 /* Skip mappings which are not marked for auto-mounting if
407 * the SHFL_MF_AUTOMOUNT flag ist set. */
408 if ( (pClient->fu32Flags & SHFL_MF_AUTOMOUNT)
409 && !pFolderMapping->fAutoMount)
410 continue;
411
412 pMappings[idx].u32Status = SHFL_MS_NEW;
413 pMappings[idx].root = i;
414 idx++;
415 }
416 cMappings++;
417 }
418 }
419
420 /* Return actual number of mappings, regardless whether the handed in
421 * mapping buffer was big enough. */
422 *pcMappings = cMappings;
423
424 LogFlow(("vbsfMappingsQuery: return rc = %Rrc\n", rc));
425 return rc;
426}
427
428#ifdef UNITTEST
429/** Unit test the SHFL_FN_QUERY_MAP_NAME API. Located here as a form of API
430 * documentation. */
431void testMappingsQueryName(RTTEST hTest)
432{
433 /* If we query an valid mapping it should be returned. */
434 testMappingsQueryNameValid(hTest);
435 /* If we query an invalid mapping that should be signalled. */
436 testMappingsQueryNameInvalid(hTest);
437 /* If we pass in a bad string buffer that should be detected. */
438 testMappingsQueryNameBadBuffer(hTest);
439}
440#endif
441int vbsfMappingsQueryName(PSHFLCLIENTDATA pClient, SHFLROOT root, SHFLSTRING *pString)
442{
443 int rc = VINF_SUCCESS;
444
445 LogFlow(("vbsfMappingsQuery: pClient = %p, root = %d, *pString = %p\n",
446 pClient, root, pString));
447
448 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
449 if (pFolderMapping == NULL)
450 {
451 return VERR_INVALID_PARAMETER;
452 }
453
454 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
455 {
456 /* Not implemented. */
457 AssertFailed();
458 return VERR_INVALID_PARAMETER;
459 }
460
461 if (pFolderMapping->fValid == true)
462 {
463 if (pString->u16Size < pFolderMapping->pMapName->u16Size)
464 {
465 Log(("vbsfMappingsQuery: passed string too short (%d < %d bytes)!\n",
466 pString->u16Size, pFolderMapping->pMapName->u16Size));
467 rc = VERR_INVALID_PARAMETER;
468 }
469 else
470 {
471 pString->u16Length = pFolderMapping->pMapName->u16Length;
472 memcpy(pString->String.ucs2, pFolderMapping->pMapName->String.ucs2,
473 pFolderMapping->pMapName->u16Size);
474 }
475 }
476 else
477 rc = VERR_FILE_NOT_FOUND;
478
479 LogFlow(("vbsfMappingsQuery:Name return rc = %Rrc\n", rc));
480
481 return rc;
482}
483
484/** Queries fWritable flag for the given root. Returns error if the root is not accessible.
485 */
486int vbsfMappingsQueryWritable(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fWritable)
487{
488 RT_NOREF1(pClient);
489 int rc = VINF_SUCCESS;
490
491 LogFlow(("vbsfMappingsQueryWritable: pClient = %p, root = %d\n", pClient, root));
492
493 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
494 AssertReturn(pFolderMapping, VERR_INVALID_PARAMETER);
495
496 if ( pFolderMapping->fValid
497 && !pFolderMapping->fMissing)
498 *fWritable = pFolderMapping->fWritable;
499 else
500 rc = VERR_FILE_NOT_FOUND;
501
502 LogFlow(("vbsfMappingsQuery:Writable return rc = %Rrc\n", rc));
503
504 return rc;
505}
506
507int vbsfMappingsQueryAutoMount(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fAutoMount)
508{
509 RT_NOREF1(pClient);
510 int rc = VINF_SUCCESS;
511
512 LogFlow(("vbsfMappingsQueryAutoMount: pClient = %p, root = %d\n", pClient, root));
513
514 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
515 AssertReturn(pFolderMapping, VERR_INVALID_PARAMETER);
516
517 if (pFolderMapping->fValid == true)
518 *fAutoMount = pFolderMapping->fAutoMount;
519 else
520 rc = VERR_FILE_NOT_FOUND;
521
522 LogFlow(("vbsfMappingsQueryAutoMount:Writable return rc = %Rrc\n", rc));
523
524 return rc;
525}
526
527int vbsfMappingsQuerySymlinksCreate(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fSymlinksCreate)
528{
529 RT_NOREF1(pClient);
530 int rc = VINF_SUCCESS;
531
532 LogFlow(("vbsfMappingsQueryAutoMount: pClient = %p, root = %d\n", pClient, root));
533
534 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
535 AssertReturn(pFolderMapping, VERR_INVALID_PARAMETER);
536
537 if (pFolderMapping->fValid == true)
538 *fSymlinksCreate = pFolderMapping->fSymlinksCreate;
539 else
540 rc = VERR_FILE_NOT_FOUND;
541
542 LogFlow(("vbsfMappingsQueryAutoMount:SymlinksCreate return rc = %Rrc\n", rc));
543
544 return rc;
545}
546
547#ifdef UNITTEST
548/** Unit test the SHFL_FN_MAP_FOLDER API. Located here as a form of API
549 * documentation. */
550void testMapFolder(RTTEST hTest)
551{
552 /* If we try to map a valid name we should get the root. */
553 testMapFolderValid(hTest);
554 /* If we try to map a valid name we should get VERR_FILE_NOT_FOUND. */
555 testMapFolderInvalid(hTest);
556 /* If we map a folder twice we can unmap it twice.
557 * Currently unmapping too often is only asserted but not signalled. */
558 testMapFolderTwice(hTest);
559 /* The delimiter should be converted in e.g. file delete operations. */
560 testMapFolderDelimiter(hTest);
561 /* Test case sensitive mapping by opening a file with the wrong case. */
562 testMapFolderCaseSensitive(hTest);
563 /* Test case insensitive mapping by opening a file with the wrong case. */
564 testMapFolderCaseInsensitive(hTest);
565 /* If the number or types of parameters are wrong the API should fail. */
566 testMapFolderBadParameters(hTest);
567}
568#endif
569int vbsfMapFolder(PSHFLCLIENTDATA pClient, PSHFLSTRING pszMapName,
570 RTUTF16 wcDelimiter, bool fCaseSensitive, SHFLROOT *pRoot)
571{
572 MAPPING *pFolderMapping = NULL;
573
574 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
575 {
576 Log(("vbsfMapFolder %s\n", pszMapName->String.utf8));
577 }
578 else
579 {
580 Log(("vbsfMapFolder %ls\n", pszMapName->String.ucs2));
581 }
582
583 AssertMsgReturn(wcDelimiter == '/' || wcDelimiter == '\\',
584 ("Invalid path delimiter: %#x\n", wcDelimiter),
585 VERR_INVALID_PARAMETER);
586 if (pClient->PathDelimiter == 0)
587 {
588 pClient->PathDelimiter = wcDelimiter;
589 }
590 else
591 {
592 AssertMsgReturn(wcDelimiter == pClient->PathDelimiter,
593 ("wcDelimiter=%#x PathDelimiter=%#x", wcDelimiter, pClient->PathDelimiter),
594 VERR_INVALID_PARAMETER);
595 }
596
597 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
598 {
599 int rc;
600 PRTUTF16 utf16Name;
601
602 rc = RTStrToUtf16 ((const char *) pszMapName->String.utf8, &utf16Name);
603 if (RT_FAILURE (rc))
604 return rc;
605
606 pFolderMapping = vbsfMappingGetByName(utf16Name, pRoot);
607 RTUtf16Free (utf16Name);
608 }
609 else
610 {
611 pFolderMapping = vbsfMappingGetByName(pszMapName->String.ucs2, pRoot);
612 }
613
614 if (!pFolderMapping)
615 {
616 return VERR_FILE_NOT_FOUND;
617 }
618
619 pFolderMapping->cMappings++;
620 Assert(pFolderMapping->cMappings == 1 || pFolderMapping->fGuestCaseSensitive == fCaseSensitive);
621 pFolderMapping->fGuestCaseSensitive = fCaseSensitive;
622 return VINF_SUCCESS;
623}
624
625#ifdef UNITTEST
626/** Unit test the SHFL_FN_UNMAP_FOLDER API. Located here as a form of API
627 * documentation. */
628void testUnmapFolder(RTTEST hTest)
629{
630 /* Unmapping a mapped folder should succeed.
631 * If the folder is not mapped this is only asserted, not signalled. */
632 testUnmapFolderValid(hTest);
633 /* Unmapping a non-existant root should fail. */
634 testUnmapFolderInvalid(hTest);
635 /* If the number or types of parameters are wrong the API should fail. */
636 testUnmapFolderBadParameters(hTest);
637}
638#endif
639int vbsfUnmapFolder(PSHFLCLIENTDATA pClient, SHFLROOT root)
640{
641 RT_NOREF1(pClient);
642 int rc = VINF_SUCCESS;
643
644 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
645 if (pFolderMapping == NULL)
646 {
647 AssertFailed();
648 return VERR_FILE_NOT_FOUND;
649 }
650
651 Assert(pFolderMapping->fValid == true && pFolderMapping->cMappings > 0);
652 if (pFolderMapping->cMappings > 0)
653 pFolderMapping->cMappings--;
654
655 if ( pFolderMapping->cMappings == 0
656 && pFolderMapping->fPlaceholder)
657 {
658 /* Automatically remove, it is not used by the guest anymore. */
659 Assert(pFolderMapping->fMissing);
660 LogRel2(("SharedFolders: unmapping placeholder '%ls' -> '%s'\n",
661 pFolderMapping->pMapName->String.ucs2, pFolderMapping->pszFolderName));
662 vbsfMappingsRemove(pFolderMapping->pMapName);
663 }
664
665 Log(("vbsfUnmapFolder\n"));
666 return rc;
667}
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