Changeset 75407 in vbox for trunk/src/VBox/HostServices/SharedFolders
- Timestamp:
- Nov 12, 2018 8:06:57 PM (6 years ago)
- Location:
- trunk/src/VBox/HostServices/SharedFolders
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedFolders/mappings.cpp
r75380 r75407 23 23 #include <iprt/alloc.h> 24 24 #include <iprt/assert.h> 25 #include <iprt/list.h> 25 26 #include <iprt/path.h> 26 27 #include <iprt/string.h> … … 30 31 #endif 31 32 32 /* Shared folders order in the saved state and in the FolderMapping can differ. 33 extern PVBOXHGCMSVCHELPERS g_pHelpers; /* service.cpp */ 34 35 36 /* Shared folders order in the saved state and in the g_FolderMapping can differ. 33 37 * So a translation array of root handle is needed. 34 38 */ 35 39 36 static MAPPING FolderMapping[SHFL_MAX_MAPPINGS]; 37 static SHFLROOT aIndexFromRoot[SHFL_MAX_MAPPINGS]; 40 static MAPPING g_FolderMapping[SHFL_MAX_MAPPINGS]; 41 static SHFLROOT g_aIndexFromRoot[SHFL_MAX_MAPPINGS]; 42 /**< Array running parallel to g_aIndexFromRoot and which entries are increased 43 * as an root handle is added or removed. 44 * 45 * This helps the guest figuring out that a mapping may have been reconfigured 46 * or that saved state has been restored. Entry reuse is very likely given that 47 * vbsfRootHandleAdd() always starts searching at the start for an unused entry. 48 */ 49 static uint32_t g_auRootHandleVersions[SHFL_MAX_MAPPINGS]; 50 /** Version number that is increased for every change made. 51 * This is used by the automount guest service to wait for changes. 52 * @note This does not need saving, the guest should be woken up and refresh 53 * its sate when restored. */ 54 static uint32_t volatile g_uFolderMappingsVersion = 0; 55 56 57 /** For recording async vbsfMappingsWaitForChanges calls. */ 58 typedef struct SHFLMAPPINGSWAIT 59 { 60 RTLISTNODE ListEntry; /**< List entry. */ 61 PSHFLCLIENTDATA pClient; /**< The client that's waiting. */ 62 VBOXHGCMCALLHANDLE hCall; /**< The call handle to signal completion with. */ 63 PVBOXHGCMSVCPARM pParm; /**< The 32-bit unsigned parameter to stuff g_uFolderMappingsVersion into. */ 64 } SHFLMAPPINGSWAIT; 65 /** Pointer to async mappings change wait. */ 66 typedef SHFLMAPPINGSWAIT *PSHFLMAPPINGSWAIT; 67 /** List head for clients waiting on mapping changes (SHFLMAPPINGSWAIT). */ 68 static RTLISTANCHOR g_MappingsChangeWaiters; 69 /** Number of clients waiting on mapping changes. 70 * We use this to limit the number of waiting calls the clients can make. */ 71 static uint32_t g_cMappingChangeWaiters = 0; 72 static void vbsfMappingsWakeupAllWaiters(void); 73 38 74 39 75 void vbsfMappingInit(void) … … 41 77 unsigned root; 42 78 43 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++) 44 { 45 aIndexFromRoot[root] = SHFL_ROOT_NIL; 46 } 47 } 48 49 int vbsfMappingLoaded(const PMAPPING pLoadedMapping, SHFLROOT root) 79 for (root = 0; root < RT_ELEMENTS(g_aIndexFromRoot); root++) 80 { 81 g_aIndexFromRoot[root] = SHFL_ROOT_NIL; 82 } 83 84 RTListInit(&g_MappingsChangeWaiters); 85 } 86 87 int vbsfMappingLoaded(const MAPPING *pLoadedMapping, SHFLROOT root) 50 88 { 51 89 /* Mapping loaded from the saved state with the index. Which means 52 90 * the guest uses the iMapping as root handle for this folder. 53 * Check whether there is the same mapping in FolderMapping and54 * update the aIndexFromRoot.91 * Check whether there is the same mapping in g_FolderMapping and 92 * update the g_aIndexFromRoot. 55 93 * 56 94 * Also update the mapping properties, which were lost: cMappings. … … 62 100 63 101 SHFLROOT i; 64 for (i = 0; i < RT_ELEMENTS( FolderMapping); i++)65 { 66 MAPPING *pMapping = & FolderMapping[i];102 for (i = 0; i < RT_ELEMENTS(g_FolderMapping); i++) 103 { 104 MAPPING *pMapping = &g_FolderMapping[i]; 67 105 68 106 /* Equal? */ … … 71 109 && memcmp(pLoadedMapping->pMapName, pMapping->pMapName, ShflStringSizeOfBuffer(pMapping->pMapName)) == 0) 72 110 { 73 /* Actual index is i. */ 74 aIndexFromRoot[root] = i; 75 76 /* Update the mapping properties. */ 77 pMapping->cMappings = pLoadedMapping->cMappings; 78 79 return VINF_SUCCESS; 111 if (!pMapping->fLoadedRootId) 112 { 113 pMapping->fLoadedRootId = true; 114 Log(("vbsfMappingLoaded: root=%u i=%u (was %u) (%ls)\n", 115 root, i, g_aIndexFromRoot[root], pLoadedMapping->pMapName->String.utf16)); 116 117 /* Actual index is i. */ 118 /** @todo This will not work with global shared folders, as these can change 119 * while state is saved and these blind assignments may hid new ones. */ 120 g_aIndexFromRoot[root] = i; 121 122 /* Update the mapping properties. */ 123 pMapping->cMappings = pLoadedMapping->cMappings; 124 125 return VINF_SUCCESS; 126 } 80 127 } 81 128 } … … 93 140 MAPPING *vbsfMappingGetByRoot(SHFLROOT root) 94 141 { 95 if (root < RT_ELEMENTS( aIndexFromRoot))96 { 97 SHFLROOT iMapping = aIndexFromRoot[root];142 if (root < RT_ELEMENTS(g_aIndexFromRoot)) 143 { 144 SHFLROOT iMapping = g_aIndexFromRoot[root]; 98 145 99 146 if ( iMapping != SHFL_ROOT_NIL 100 && iMapping < RT_ELEMENTS( FolderMapping))101 { 102 return & FolderMapping[iMapping];147 && iMapping < RT_ELEMENTS(g_FolderMapping)) 148 { 149 return &g_FolderMapping[iMapping]; 103 150 } 104 151 } … … 111 158 unsigned root; 112 159 113 for (root = 0; root < RT_ELEMENTS( aIndexFromRoot); root++)114 { 115 if (iMapping == aIndexFromRoot[root])160 for (root = 0; root < RT_ELEMENTS(g_aIndexFromRoot); root++) 161 { 162 if (iMapping == g_aIndexFromRoot[root]) 116 163 { 117 164 return root; … … 122 169 } 123 170 124 static MAPPING *vbsfMappingGetByName (PRTUTF16 pwszName, SHFLROOT *pRoot) 125 { 126 unsigned i; 127 128 for (i=0; i<SHFL_MAX_MAPPINGS; i++) 129 { 130 if (FolderMapping[i].fValid == true) 131 { 132 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pwszName)) 171 static MAPPING *vbsfMappingGetByName(PRTUTF16 pwszName, SHFLROOT *pRoot) 172 { 173 for (unsigned i = 0; i < SHFL_MAX_MAPPINGS; i++) 174 { 175 if ( g_FolderMapping[i].fValid 176 && !g_FolderMapping[i].fPlaceholder) /* Don't allow mapping placeholders. */ 177 { 178 if (!RTUtf16LocaleICmp(g_FolderMapping[i].pMapName->String.ucs2, pwszName)) 133 179 { 134 180 SHFLROOT root = vbsfMappingGetRootFromIndex(i); … … 140 186 *pRoot = root; 141 187 } 142 return & FolderMapping[i];188 return &g_FolderMapping[i]; 143 189 } 144 else 145 { 146 AssertFailed(); 147 } 190 AssertFailed(); 148 191 } 149 192 } 150 193 } 151 152 194 return NULL; 153 195 } … … 157 199 unsigned root; 158 200 159 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++) 160 { 161 if (aIndexFromRoot[root] == SHFL_ROOT_NIL) 162 { 163 aIndexFromRoot[root] = iMapping; 201 for (root = 0; root < RT_ELEMENTS(g_aIndexFromRoot); root++) 202 { 203 if (g_aIndexFromRoot[root] == SHFL_ROOT_NIL) 204 { 205 g_aIndexFromRoot[root] = iMapping; 206 g_auRootHandleVersions[root] += 1; 164 207 return; 165 208 } … … 173 216 unsigned root; 174 217 175 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++) 176 { 177 if (aIndexFromRoot[root] == iMapping) 178 { 179 aIndexFromRoot[root] = SHFL_ROOT_NIL; 180 return; 218 for (root = 0; root < RT_ELEMENTS(g_aIndexFromRoot); root++) 219 { 220 if (g_aIndexFromRoot[root] == iMapping) 221 { 222 g_aIndexFromRoot[root] = SHFL_ROOT_NIL; 223 g_auRootHandleVersions[root] += 1; 224 Log(("vbsfRootHandleRemove: Removed root=%u (iMapping=%u)\n", root, iMapping)); 225 226 /* Note! Do not stop here as g_aIndexFromRoot may (at least it could 227 prior to the introduction of fLoadedRootId) contain 228 duplicates after restoring save state. */ 181 229 } 182 230 } … … 209 257 Log(("vbsfMappingsAdd %ls\n", pMapName->String.ucs2)); 210 258 211 /* check for duplicates */ 212 for (i=0; i<SHFL_MAX_MAPPINGS; i++) 213 { 214 if (FolderMapping[i].fValid == true) 215 { 216 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) 259 /* Check for duplicates, ignoring placeholders to give the GUI to change stuff at runtime. */ 260 /** @todo bird: Not entirely sure about ignoring placeholders, but you cannot 261 * trigger auto-umounting without ignoring them. */ 262 if (!fPlaceholder) 263 { 264 for (i = 0; i < SHFL_MAX_MAPPINGS; i++) 265 { 266 if ( g_FolderMapping[i].fValid 267 && !g_FolderMapping[i].fPlaceholder) 217 268 { 218 AssertMsgFailed(("vbsfMappingsAdd: %ls mapping already exists!!\n", pMapName->String.ucs2)); 219 return VERR_ALREADY_EXISTS; 269 if (!RTUtf16LocaleICmp(g_FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) 270 { 271 AssertMsgFailed(("vbsfMappingsAdd: %ls mapping already exists!!\n", pMapName->String.ucs2)); 272 return VERR_ALREADY_EXISTS; 273 } 220 274 } 221 275 } 222 276 } 223 277 224 for (i =0; i<SHFL_MAX_MAPPINGS; i++)225 { 226 if ( FolderMapping[i].fValid == false)278 for (i = 0; i < SHFL_MAX_MAPPINGS; i++) 279 { 280 if (g_FolderMapping[i].fValid == false) 227 281 { 228 282 /* Make sure the folder name is an absolute path, otherwise we're … … 232 286 AssertRCReturn(rc, rc); 233 287 234 FolderMapping[i].pszFolderName = RTStrDup(szAbsFolderName);235 FolderMapping[i].pMapName = ShflStringDup(pMapName);236 FolderMapping[i].pAutoMountPoint = ShflStringDup(pAutoMountPoint);237 if ( ! FolderMapping[i].pszFolderName238 || ! FolderMapping[i].pMapName239 || ! FolderMapping[i].pAutoMountPoint)288 g_FolderMapping[i].pszFolderName = RTStrDup(szAbsFolderName); 289 g_FolderMapping[i].pMapName = ShflStringDup(pMapName); 290 g_FolderMapping[i].pAutoMountPoint = ShflStringDup(pAutoMountPoint); 291 if ( !g_FolderMapping[i].pszFolderName 292 || !g_FolderMapping[i].pMapName 293 || !g_FolderMapping[i].pAutoMountPoint) 240 294 { 241 RTStrFree( FolderMapping[i].pszFolderName);242 RTMemFree( FolderMapping[i].pMapName);243 RTMemFree( FolderMapping[i].pAutoMountPoint);295 RTStrFree(g_FolderMapping[i].pszFolderName); 296 RTMemFree(g_FolderMapping[i].pMapName); 297 RTMemFree(g_FolderMapping[i].pAutoMountPoint); 244 298 return VERR_NO_MEMORY; 245 299 } 246 300 247 FolderMapping[i].fValid = true; 248 FolderMapping[i].cMappings = 0; 249 FolderMapping[i].fWritable = fWritable; 250 FolderMapping[i].fAutoMount = fAutoMount; 251 FolderMapping[i].fSymlinksCreate = fSymlinksCreate; 252 FolderMapping[i].fMissing = fMissing; 253 FolderMapping[i].fPlaceholder = fPlaceholder; 301 g_FolderMapping[i].fValid = true; 302 g_FolderMapping[i].cMappings = 0; 303 g_FolderMapping[i].fWritable = fWritable; 304 g_FolderMapping[i].fAutoMount = fAutoMount; 305 g_FolderMapping[i].fSymlinksCreate = fSymlinksCreate; 306 g_FolderMapping[i].fMissing = fMissing; 307 g_FolderMapping[i].fPlaceholder = fPlaceholder; 308 g_FolderMapping[i].fLoadedRootId = false; 254 309 255 310 /* Check if the host file system is case sensitive */ 256 311 RTFSPROPERTIES prop; 257 312 prop.fCaseSensitive = false; /* Shut up MSC. */ 258 rc = RTFsQueryProperties( FolderMapping[i].pszFolderName, &prop);313 rc = RTFsQueryProperties(g_FolderMapping[i].pszFolderName, &prop); 259 314 AssertRC(rc); 260 FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false;315 g_FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false; 261 316 vbsfRootHandleAdd(i); 317 vbsfMappingsWakeupAllWaiters(); 262 318 break; 263 319 } … … 269 325 } 270 326 271 Log(("vbsfMappingsAdd: added mapping %s to %ls\n", pszFolderName, pMapName->String.ucs2)); 327 Log(("vbsfMappingsAdd: added mapping %s to %ls (slot %u, root %u)\n", 328 pszFolderName, pMapName->String.ucs2, i, vbsfMappingGetRootFromIndex(i))); 272 329 return VINF_SUCCESS; 273 330 } … … 285 342 int vbsfMappingsRemove(PSHFLSTRING pMapName) 286 343 { 287 unsigned i;288 289 344 Assert(pMapName); 290 291 345 Log(("vbsfMappingsRemove %ls\n", pMapName->String.ucs2)); 292 for (i=0; i<SHFL_MAX_MAPPINGS; i++) 293 { 294 if (FolderMapping[i].fValid == true) 295 { 296 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) 346 347 /* 348 * We must iterate thru the whole table as may have 0+ placeholder entries 349 * and 0-1 regular entries with the same name. Also, it is good to kick 350 * the guest automounter into action wrt to evicting placeholders. 351 */ 352 int rc = VERR_FILE_NOT_FOUND; 353 for (unsigned i = 0; i < SHFL_MAX_MAPPINGS; i++) 354 { 355 if (g_FolderMapping[i].fValid == true) 356 { 357 if (!RTUtf16LocaleICmp(g_FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2)) 297 358 { 298 if ( FolderMapping[i].cMappings != 0)359 if (g_FolderMapping[i].cMappings != 0) 299 360 { 300 LogRel2(("SharedFolders: removing '%ls' -> '%s', which is still used by the guest\n", 301 pMapName->String.ucs2, FolderMapping[i].pszFolderName)); 302 FolderMapping[i].fMissing = true; 303 FolderMapping[i].fPlaceholder = true; 304 return VINF_PERMISSION_DENIED; 361 LogRel2(("SharedFolders: removing '%ls' -> '%s'%s, which is still used by the guest\n", pMapName->String.ucs2, 362 g_FolderMapping[i].pszFolderName, g_FolderMapping[i].fPlaceholder ? " (again)" : "")); 363 g_FolderMapping[i].fMissing = true; 364 g_FolderMapping[i].fPlaceholder = true; 365 vbsfMappingsWakeupAllWaiters(); 366 rc = VINF_PERMISSION_DENIED; 305 367 } 306 307 /* pMapName can be the same as FolderMapping[i].pMapName, 308 * log it before deallocating the memory. 309 */ 310 Log(("vbsfMappingsRemove: mapping %ls removed\n", pMapName->String.ucs2)); 311 312 RTStrFree(FolderMapping[i].pszFolderName); 313 RTMemFree(FolderMapping[i].pMapName); 314 FolderMapping[i].pszFolderName = NULL; 315 FolderMapping[i].pMapName = NULL; 316 FolderMapping[i].fValid = false; 317 vbsfRootHandleRemove(i); 318 return VINF_SUCCESS; 368 else 369 { 370 /* pMapName can be the same as g_FolderMapping[i].pMapName when 371 * called from vbsfUnmapFolder, log it before deallocating the memory. */ 372 Log(("vbsfMappingsRemove: mapping %ls removed\n", pMapName->String.ucs2)); 373 bool fSame = g_FolderMapping[i].pMapName == pMapName; 374 375 RTStrFree(g_FolderMapping[i].pszFolderName); 376 RTMemFree(g_FolderMapping[i].pMapName); 377 g_FolderMapping[i].pszFolderName = NULL; 378 g_FolderMapping[i].pMapName = NULL; 379 g_FolderMapping[i].fValid = false; 380 vbsfRootHandleRemove(i); 381 vbsfMappingsWakeupAllWaiters(); 382 if (rc == VERR_FILE_NOT_FOUND) 383 rc = VINF_SUCCESS; 384 if (fSame) 385 break; 386 } 319 387 } 320 388 } 321 389 } 322 390 323 AssertMsgFailed(("vbsfMappingsRemove: mapping %ls not found!!!!\n", pMapName->String.ucs2)); 324 return VERR_FILE_NOT_FOUND; 391 return rc; 325 392 } 326 393 … … 378 445 #endif 379 446 /** 380 * Note: If pMappings / *pcMappings is smaller than the actual amount of mappings 381 * that *could* have been returned *pcMappings contains the required buffer size 382 * so that the caller can retry the operation if wanted. 383 */ 384 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, PSHFLMAPPING pMappings, uint32_t *pcMappings) 385 { 386 int rc = VINF_SUCCESS; 387 388 uint32_t cMappings = 0; /* Will contain actual valid mappings. */ 389 uint32_t idx = 0; /* Current index in mappings buffer. */ 390 447 * @note If pMappings / *pcMappings is smaller than the actual amount of 448 * mappings that *could* have been returned *pcMappings contains the 449 * required buffer size so that the caller can retry the operation if 450 * wanted. 451 */ 452 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, bool fOnlyAutoMounts, PSHFLMAPPING pMappings, uint32_t *pcMappings) 453 { 391 454 LogFlow(("vbsfMappingsQuery: pClient = %p, pMappings = %p, pcMappings = %p, *pcMappings = %d\n", 392 455 pClient, pMappings, pcMappings, *pcMappings)); 393 456 457 uint32_t const cMaxMappings = *pcMappings; 458 uint32_t idx = 0; 394 459 for (uint32_t i = 0; i < SHFL_MAX_MAPPINGS; i++) 395 460 { 396 461 MAPPING *pFolderMapping = vbsfMappingGetByRoot(i); 397 462 if ( pFolderMapping != NULL 398 && pFolderMapping->fValid == true) 399 { 400 if (idx < *pcMappings) 463 && pFolderMapping->fValid 464 && ( !fOnlyAutoMounts 465 || (pFolderMapping->fAutoMount && !pFolderMapping->fPlaceholder)) ) 466 { 467 if (idx < cMaxMappings) 401 468 { 402 /* Skip mappings which are not marked for auto-mounting if403 * the SHFL_MF_AUTOMOUNT flag ist set. */404 if ( (pClient->fu32Flags & SHFL_MF_AUTOMOUNT)405 && !pFolderMapping->fAutoMount)406 continue;407 408 469 pMappings[idx].u32Status = SHFL_MS_NEW; 409 pMappings[idx].root = i; 410 idx++; 470 pMappings[idx].root = i; 411 471 } 412 cMappings++;472 idx++; 413 473 } 414 474 } … … 416 476 /* Return actual number of mappings, regardless whether the handed in 417 477 * mapping buffer was big enough. */ 418 *pcMappings = cMappings; 419 420 LogFlow(("vbsfMappingsQuery: return rc = %Rrc\n", rc)); 421 return rc; 478 /** @todo r=bird: This is non-standard interface behaviour. We return 479 * VERR_BUFFER_OVERFLOW or at least a VINF_BUFFER_OVERFLOW here. 480 * 481 * Guess this goes well along with ORing SHFL_MF_AUTOMOUNT into 482 * pClient->fu32Flags rather than passing it as fOnlyAutoMounts... 483 * Not amused by this. */ 484 *pcMappings = idx; 485 486 LogFlow(("vbsfMappingsQuery: returns VINF_SUCCESS (idx=%u, cMaxMappings=%u)\n", idx, cMaxMappings)); 487 return VINF_SUCCESS; 422 488 } 423 489 … … 437 503 int vbsfMappingsQueryName(PSHFLCLIENTDATA pClient, SHFLROOT root, SHFLSTRING *pString) 438 504 { 439 int rc = VINF_SUCCESS; 440 441 LogFlow(("vbsfMappingsQuery: pClient = %p, root = %d, *pString = %p\n", 442 pClient, root, pString)); 443 505 LogFlow(("vbsfMappingsQuery: pClient = %p, root = %d, *pString = %p\n", pClient, root, pString)); 506 507 int rc; 444 508 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root); 445 if (pFolderMapping == NULL) 446 { 447 return VERR_INVALID_PARAMETER; 448 } 449 450 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8)) 451 { 452 /* Not implemented. */ 453 AssertFailed(); 454 return VERR_INVALID_PARAMETER; 455 } 456 457 if (pFolderMapping->fValid == true) 458 { 459 if (pString->u16Size < pFolderMapping->pMapName->u16Size) 460 { 461 Log(("vbsfMappingsQuery: passed string too short (%d < %d bytes)!\n", 462 pString->u16Size, pFolderMapping->pMapName->u16Size)); 463 rc = VERR_INVALID_PARAMETER; 509 if (pFolderMapping) 510 { 511 if (pFolderMapping->fValid) 512 { 513 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8)) 514 rc = ShflStringCopyUtf16BufAsUtf8(pString, pFolderMapping->pMapName); 515 else 516 { 517 /* Not using ShlfStringCopy here as behaviour shouldn't change... */ 518 if (pString->u16Size < pFolderMapping->pMapName->u16Size) 519 { 520 Log(("vbsfMappingsQuery: passed string too short (%d < %d bytes)!\n", 521 pString->u16Size, pFolderMapping->pMapName->u16Size)); 522 rc = VERR_INVALID_PARAMETER; 523 } 524 else 525 { 526 pString->u16Length = pFolderMapping->pMapName->u16Length; 527 memcpy(pString->String.ucs2, pFolderMapping->pMapName->String.ucs2, 528 pFolderMapping->pMapName->u16Size); 529 rc = VINF_SUCCESS; 530 } 531 } 464 532 } 465 533 else 466 { 467 pString->u16Length = pFolderMapping->pMapName->u16Length; 468 memcpy(pString->String.ucs2, pFolderMapping->pMapName->String.ucs2, 469 pFolderMapping->pMapName->u16Size); 470 } 534 rc = VERR_FILE_NOT_FOUND; 471 535 } 472 536 else 473 rc = VERR_ FILE_NOT_FOUND;537 rc = VERR_INVALID_PARAMETER; 474 538 475 539 LogFlow(("vbsfMappingsQuery:Name return rc = %Rrc\n", rc)); 476 477 540 return rc; 478 541 } … … 540 603 return rc; 541 604 } 605 606 /** 607 * Implements SHFL_FN_QUERY_MAP_INFO. 608 * @since VBox 6.0 609 */ 610 int vbsfMappingsQueryInfo(PSHFLCLIENTDATA pClient, SHFLROOT root, PSHFLSTRING pNameBuf, PSHFLSTRING pMntPtBuf, 611 uint64_t *pfFlags, uint32_t *puVersion) 612 { 613 LogFlow(("vbsfMappingsQueryInfo: pClient=%p root=%d\n", pClient, root)); 614 615 /* Resolve the root handle. */ 616 int rc; 617 PMAPPING pFolderMapping = vbsfMappingGetByRoot(root); 618 if (pFolderMapping) 619 { 620 if (pFolderMapping->fValid) 621 { 622 /* 623 * Produce the output. 624 */ 625 *puVersion = g_auRootHandleVersions[root]; 626 627 *pfFlags = 0; 628 if (pFolderMapping->fWritable) 629 *pfFlags |= SHFL_MIF_WRITABLE; 630 if (pFolderMapping->fAutoMount) 631 *pfFlags |= SHFL_MIF_AUTO_MOUNT; 632 if (pFolderMapping->fHostCaseSensitive) 633 *pfFlags |= SHFL_MIF_HOST_ICASE; 634 if (pFolderMapping->fGuestCaseSensitive) 635 *pfFlags |= SHFL_MIF_GUEST_ICASE; 636 if (pFolderMapping->fSymlinksCreate) 637 *pfFlags |= SHFL_MIF_SYMLINK_CREATION; 638 639 int rc2; 640 if (pClient->fu32Flags & SHFL_CF_UTF8) 641 { 642 rc = ShflStringCopyUtf16BufAsUtf8(pNameBuf, pFolderMapping->pMapName); 643 rc2 = ShflStringCopyUtf16BufAsUtf8(pMntPtBuf, pFolderMapping->pAutoMountPoint); 644 } 645 else 646 { 647 rc = ShflStringCopy(pNameBuf, pFolderMapping->pMapName, sizeof(RTUTF16)); 648 rc2 = ShflStringCopy(pMntPtBuf, pFolderMapping->pAutoMountPoint, sizeof(RTUTF16)); 649 } 650 if (RT_SUCCESS(rc)) 651 rc = rc2; 652 } 653 else 654 rc = VERR_FILE_NOT_FOUND; 655 } 656 else 657 rc = VERR_INVALID_PARAMETER; 658 LogFlow(("vbsfMappingsQueryInfo: returns %Rrc\n", rc)); 659 return rc; 660 } 661 662 542 663 543 664 #ifdef UNITTEST … … 662 783 return rc; 663 784 } 785 786 /** 787 * SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES implementation. 788 * 789 * @returns VBox status code. 790 * @retval VINF_SUCCESS on change. 791 * @retval VINF_TRY_AGAIN on resume. 792 * @retval VINF_HGCM_ASYNC_EXECUTE if waiting. 793 * @retval VERR_CANCELLED if cancelled. 794 * @retval VERR_OUT_OF_RESOURCES if there are too many pending waits. 795 * 796 * @param pClient The calling client. 797 * @param hCall The call handle. 798 * @param pParm The parameter (32-bit). 799 * @param fRestored Set if this is a call restored & resubmitted from saved 800 * state. 801 * @since VBox 6.0 802 */ 803 int vbsfMappingsWaitForChanges(PSHFLCLIENTDATA pClient, VBOXHGCMCALLHANDLE hCall, PVBOXHGCMSVCPARM pParm, bool fRestored) 804 { 805 /* 806 * Return immediately if the fodler mappings have changed since last call 807 * or if we got restored from saved state (adding of global folders, etc). 808 */ 809 uint32_t uCurVersion = g_uFolderMappingsVersion; 810 if ( pParm->u.uint32 != uCurVersion 811 || fRestored 812 || (pClient->fu32Flags & SHFL_CF_CANCEL_NEXT_WAIT) ) 813 { 814 int rc = VINF_SUCCESS; 815 if (pClient->fu32Flags & SHFL_CF_CANCEL_NEXT_WAIT) 816 { 817 pClient->fu32Flags &= ~SHFL_CF_CANCEL_NEXT_WAIT; 818 rc = VERR_CANCELLED; 819 } 820 else if (fRestored) 821 { 822 rc = VINF_TRY_AGAIN; 823 if (pParm->u.uint32 == uCurVersion) 824 uCurVersion = uCurVersion != UINT32_C(0x55555555) ? UINT32_C(0x55555555) : UINT32_C(0x99999999); 825 } 826 Log(("vbsfMappingsWaitForChanges: Version %#x -> %#x, returning %Rrc immediately.\n", pParm->u.uint32, uCurVersion, rc)); 827 pParm->u.uint32 = uCurVersion; 828 return rc; 829 } 830 831 /* 832 * Setup a wait if we can. 833 */ 834 if (g_cMappingChangeWaiters < 64) 835 { 836 PSHFLMAPPINGSWAIT pWait = (PSHFLMAPPINGSWAIT)RTMemAlloc(sizeof(*pWait)); 837 if (pWait) 838 { 839 pWait->pClient = pClient; 840 pWait->hCall = hCall; 841 pWait->pParm = pParm; 842 843 RTListAppend(&g_MappingsChangeWaiters, &pWait->ListEntry); 844 g_cMappingChangeWaiters += 1; 845 return VINF_HGCM_ASYNC_EXECUTE; 846 } 847 return VERR_NO_MEMORY; 848 } 849 LogRelMax(32, ("vbsfMappingsWaitForChanges: Too many threads waiting for changes!\n")); 850 return VERR_OUT_OF_RESOURCES; 851 } 852 853 /** 854 * SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS implementation. 855 * 856 * @returns VINF_SUCCESS 857 * @param pClient The calling client to cancel all waits for. 858 * @since VBox 6.0 859 */ 860 int vbsfMappingsCancelChangesWaits(PSHFLCLIENTDATA pClient) 861 { 862 uint32_t const uCurVersion = g_uFolderMappingsVersion; 863 864 PSHFLMAPPINGSWAIT pCur, pNext; 865 RTListForEachSafe(&g_MappingsChangeWaiters, pCur, pNext, SHFLMAPPINGSWAIT, ListEntry) 866 { 867 if (pCur->pClient == pClient) 868 { 869 RTListNodeRemove(&pCur->ListEntry); 870 pCur->pParm->u.uint32 = uCurVersion; 871 g_pHelpers->pfnCallComplete(pCur->hCall, VERR_CANCELLED); 872 RTMemFree(pCur); 873 } 874 } 875 876 /* Set a flag to make sure the next SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES doesn't block. 877 This should help deal with races between this call and a thread about to do a wait. */ 878 pClient->fu32Flags |= SHFL_CF_CANCEL_NEXT_WAIT; 879 880 return VINF_SUCCESS; 881 } 882 883 /** 884 * Wakes up all clients waiting on 885 */ 886 static void vbsfMappingsWakeupAllWaiters(void) 887 { 888 uint32_t const uCurVersion = ++g_uFolderMappingsVersion; 889 890 PSHFLMAPPINGSWAIT pCur, pNext; 891 RTListForEachSafe(&g_MappingsChangeWaiters, pCur, pNext, SHFLMAPPINGSWAIT, ListEntry) 892 { 893 RTListNodeRemove(&pCur->ListEntry); 894 pCur->pParm->u.uint32 = uCurVersion; 895 g_pHelpers->pfnCallComplete(pCur->hCall, VERR_CANCELLED); 896 RTMemFree(pCur); 897 } 898 } 899 -
trunk/src/VBox/HostServices/SharedFolders/mappings.h
r75380 r75407 38 38 bool fPlaceholder; /**< Mapping does not exist in the VM settings but the guest 39 39 still has. fMissing is always true for this mapping. */ 40 bool fLoadedRootId; /**< Set if vbsfMappingLoaded has found this mapping already. */ 40 41 } MAPPING; 41 42 /** Pointer to a MAPPING structure. */ … … 50 51 int vbsfMappingsRemove(PSHFLSTRING pMapName); 51 52 52 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, PSHFLMAPPING pMappings, uint32_t *pcMappings);53 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, bool fOnlyAutoMounts, PSHFLMAPPING pMappings, uint32_t *pcMappings); 53 54 int vbsfMappingsQueryName(PSHFLCLIENTDATA pClient, SHFLROOT root, SHFLSTRING *pString); 54 55 int vbsfMappingsQueryWritable(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fWritable); 55 56 int vbsfMappingsQueryAutoMount(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fAutoMount); 56 57 int vbsfMappingsQuerySymlinksCreate(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fSymlinksCreate); 58 int vbsfMappingsQueryInfo(PSHFLCLIENTDATA pClient, SHFLROOT root, PSHFLSTRING pNameBuf, PSHFLSTRING pMntPtBuf, 59 uint64_t *pfFlags, uint32_t *puVersion); 57 60 58 61 int vbsfMapFolder(PSHFLCLIENTDATA pClient, PSHFLSTRING pszMapName, RTUTF16 delimiter, 59 62 bool fCaseSensitive, SHFLROOT *pRoot); 60 63 int vbsfUnmapFolder(PSHFLCLIENTDATA pClient, SHFLROOT root); 64 65 int vbsfMappingsWaitForChanges(PSHFLCLIENTDATA pClient, VBOXHGCMCALLHANDLE hCall, PVBOXHGCMSVCPARM pParm, bool fRestored); 66 int vbsfMappingsCancelChangesWaits(PSHFLCLIENTDATA pClient); 61 67 62 68 const char* vbsfMappingsQueryHostRoot(SHFLROOT root); … … 65 71 bool vbsfIsHostMappingCaseSensitive(SHFLROOT root); 66 72 67 int vbsfMappingLoaded( const PMAPPINGpLoadedMapping, SHFLROOT root);73 int vbsfMappingLoaded(MAPPING const *pLoadedMapping, SHFLROOT root); 68 74 PMAPPING vbsfMappingGetByRoot(SHFLROOT root); 69 75 -
trunk/src/VBox/HostServices/SharedFolders/service.cpp
r75380 r75407 26 26 #include <iprt/string.h> 27 27 #include <iprt/assert.h> 28 #include <VBox/AssertGuest.h> 28 29 #include <VBox/vmm/ssm.h> 29 30 #include <VBox/vmm/pdmifs.h> … … 237 238 rc = SSMR3GetMem(pSSM, pFolderName, cb); 238 239 AssertRCReturn(rc, rc); 239 AssertReturn(pFolderName->u16 Length < cb && pFolderName->u16Size < pFolderName->u16Length,240 AssertReturn(pFolderName->u16Size < cb && pFolderName->u16Length < pFolderName->u16Size, 240 241 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 241 242 "Bad folder name string: %#x/%#x cb=%#x\n", … … 267 268 rc = SSMR3GetMem(pSSM, pMapName, cb); 268 269 AssertRCReturn(rc, rc); 269 AssertReturn(pMapName->u16 Length < cb && pMapName->u16Size < pMapName->u16Length,270 AssertReturn(pMapName->u16Size < cb && pMapName->u16Length < pMapName->u16Size, 270 271 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 271 272 "Bad map name string: %#x/%#x cb=%#x\n", … … 293 294 rc = SSMR3GetMem(pSSM, pAutoMountPoint, cb); 294 295 AssertRCReturn(rc, rc); 295 AssertReturn(pAutoMountPoint->u16 Length < cb && pAutoMountPoint->u16Size < pAutoMountPoint->u16Length,296 AssertReturn(pAutoMountPoint->u16Size < cb && pAutoMountPoint->u16Length < pAutoMountPoint->u16Size, 296 297 SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 297 298 "Bad auto mount point string: %#x/%#x cb=%#x\n", … … 331 332 } 332 333 333 static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 334 static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, 335 void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 334 336 { 335 337 RT_NOREF1(u32ClientID); … … 388 390 if (fu32Flags & SHFL_MF_UTF8) 389 391 pClient->fu32Flags |= SHFL_CF_UTF8; 390 if (fu32Flags & SHFL_MF_AUTOMOUNT) 391 pClient->fu32Flags |= SHFL_MF_AUTOMOUNT; 392 393 rc = vbsfMappingsQuery(pClient, pMappings, &cMappings); 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); 394 399 if (RT_SUCCESS(rc)) 395 400 { … … 1295 1300 } 1296 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 1297 1354 default: 1298 1355 { -
trunk/src/VBox/HostServices/SharedFolders/shfl.h
r69500 r75407 43 43 #define SHFL_CF_SYMLINKS (0x00000008) 44 44 45 /** The call to SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES will return immediately 46 * because of a SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS call. */ 47 #define SHFL_CF_CANCEL_NEXT_WAIT (0x00000010) 48 45 49 /** @} */ 46 50 -
trunk/src/VBox/HostServices/SharedFolders/vbsf.h
r69500 r75407 1 /* $Id$ */ 1 2 /** @file 2 3 * VBox Shared Folders header. … … 15 16 */ 16 17 17 #ifndef __ VBSF__H18 #define __ VBSF__H18 #ifndef ___vbsf_h___ 19 #define ___vbsf_h___ 19 20 20 21 #include "shfl.h" … … 41 42 int vbsfSymlink(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pNewPath, SHFLSTRING *pOldPath, SHFLFSOBJINFO *pInfo); 42 43 43 #endif /* __VBSF__H */ 44 #endif /* !___vbsf_h___ */ 45
Note:
See TracChangeset
for help on using the changeset viewer.