VirtualBox

Ignore:
Timestamp:
Nov 12, 2018 8:06:57 PM (6 years ago)
Author:
vboxsync
Message:

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.
Location:
trunk/src/VBox/HostServices/SharedFolders
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedFolders/mappings.cpp

    r75380 r75407  
    2323#include <iprt/alloc.h>
    2424#include <iprt/assert.h>
     25#include <iprt/list.h>
    2526#include <iprt/path.h>
    2627#include <iprt/string.h>
     
    3031#endif
    3132
    32 /* Shared folders order in the saved state and in the FolderMapping can differ.
     33extern PVBOXHGCMSVCHELPERS g_pHelpers; /* service.cpp */
     34
     35
     36/* Shared folders order in the saved state and in the g_FolderMapping can differ.
    3337 * So a translation array of root handle is needed.
    3438 */
    3539
    36 static MAPPING FolderMapping[SHFL_MAX_MAPPINGS];
    37 static SHFLROOT aIndexFromRoot[SHFL_MAX_MAPPINGS];
     40static MAPPING g_FolderMapping[SHFL_MAX_MAPPINGS];
     41static 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 */
     49static 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. */
     54static uint32_t volatile g_uFolderMappingsVersion = 0;
     55
     56
     57/** For recording async vbsfMappingsWaitForChanges calls. */
     58typedef 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. */
     66typedef SHFLMAPPINGSWAIT *PSHFLMAPPINGSWAIT;
     67/** List head for clients waiting on mapping changes (SHFLMAPPINGSWAIT). */
     68static 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.  */
     71static uint32_t     g_cMappingChangeWaiters = 0;
     72static void vbsfMappingsWakeupAllWaiters(void);
     73
    3874
    3975void vbsfMappingInit(void)
     
    4177    unsigned root;
    4278
    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
     87int vbsfMappingLoaded(const MAPPING *pLoadedMapping, SHFLROOT root)
    5088{
    5189    /* Mapping loaded from the saved state with the index. Which means
    5290     * the guest uses the iMapping as root handle for this folder.
    53      * Check whether there is the same mapping in FolderMapping and
    54      * update the aIndexFromRoot.
     91     * Check whether there is the same mapping in g_FolderMapping and
     92     * update the g_aIndexFromRoot.
    5593     *
    5694     * Also update the mapping properties, which were lost: cMappings.
     
    62100
    63101    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];
    67105
    68106        /* Equal? */
     
    71109            && memcmp(pLoadedMapping->pMapName, pMapping->pMapName, ShflStringSizeOfBuffer(pMapping->pMapName)) == 0)
    72110        {
    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            }
    80127        }
    81128    }
     
    93140MAPPING *vbsfMappingGetByRoot(SHFLROOT root)
    94141{
    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];
    98145
    99146        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];
    103150        }
    104151    }
     
    111158    unsigned root;
    112159
    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])
    116163        {
    117164            return root;
     
    122169}
    123170
    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))
     171static 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))
    133179            {
    134180                SHFLROOT root = vbsfMappingGetRootFromIndex(i);
     
    140186                        *pRoot = root;
    141187                    }
    142                     return &FolderMapping[i];
     188                    return &g_FolderMapping[i];
    143189                }
    144                 else
    145                 {
    146                     AssertFailed();
    147                 }
     190                AssertFailed();
    148191            }
    149192        }
    150193    }
    151 
    152194    return NULL;
    153195}
     
    157199    unsigned root;
    158200
    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;
    164207            return;
    165208        }
     
    173216    unsigned root;
    174217
    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. */
    181229        }
    182230    }
     
    209257    Log(("vbsfMappingsAdd %ls\n", pMapName->String.ucs2));
    210258
    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)
    217268            {
    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                }
    220274            }
    221275        }
    222276    }
    223277
    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)
    227281        {
    228282            /* Make sure the folder name is an absolute path, otherwise we're
     
    232286            AssertRCReturn(rc, rc);
    233287
    234             FolderMapping[i].pszFolderName   = RTStrDup(szAbsFolderName);
    235             FolderMapping[i].pMapName        = ShflStringDup(pMapName);
    236             FolderMapping[i].pAutoMountPoint = ShflStringDup(pAutoMountPoint);
    237             if (   !FolderMapping[i].pszFolderName
    238                 || !FolderMapping[i].pMapName
    239                 || !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)
    240294            {
    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);
    244298                return VERR_NO_MEMORY;
    245299            }
    246300
    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;
    254309
    255310            /* Check if the host file system is case sensitive */
    256311            RTFSPROPERTIES prop;
    257312            prop.fCaseSensitive = false; /* Shut up MSC. */
    258             rc = RTFsQueryProperties(FolderMapping[i].pszFolderName, &prop);
     313            rc = RTFsQueryProperties(g_FolderMapping[i].pszFolderName, &prop);
    259314            AssertRC(rc);
    260             FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false;
     315            g_FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false;
    261316            vbsfRootHandleAdd(i);
     317            vbsfMappingsWakeupAllWaiters();
    262318            break;
    263319        }
     
    269325    }
    270326
    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)));
    272329    return VINF_SUCCESS;
    273330}
     
    285342int vbsfMappingsRemove(PSHFLSTRING pMapName)
    286343{
    287     unsigned i;
    288 
    289344    Assert(pMapName);
    290 
    291345    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))
    297358            {
    298                 if (FolderMapping[i].cMappings != 0)
     359                if (g_FolderMapping[i].cMappings != 0)
    299360                {
    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;
    305367                }
    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                }
    319387            }
    320388        }
    321389    }
    322390
    323     AssertMsgFailed(("vbsfMappingsRemove: mapping %ls not found!!!!\n", pMapName->String.ucs2));
    324     return VERR_FILE_NOT_FOUND;
     391    return rc;
    325392}
    326393
     
    378445#endif
    379446/**
    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 */
     452int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, bool fOnlyAutoMounts, PSHFLMAPPING pMappings, uint32_t *pcMappings)
     453{
    391454    LogFlow(("vbsfMappingsQuery: pClient = %p, pMappings = %p, pcMappings = %p, *pcMappings = %d\n",
    392455             pClient, pMappings, pcMappings, *pcMappings));
    393456
     457    uint32_t const cMaxMappings = *pcMappings;
     458    uint32_t       idx          = 0;
    394459    for (uint32_t i = 0; i < SHFL_MAX_MAPPINGS; i++)
    395460    {
    396461        MAPPING *pFolderMapping = vbsfMappingGetByRoot(i);
    397462        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)
    401468            {
    402                 /* Skip mappings which are not marked for auto-mounting if
    403                  * the SHFL_MF_AUTOMOUNT flag ist set. */
    404                 if (   (pClient->fu32Flags & SHFL_MF_AUTOMOUNT)
    405                     && !pFolderMapping->fAutoMount)
    406                     continue;
    407 
    408469                pMappings[idx].u32Status = SHFL_MS_NEW;
    409                 pMappings[idx].root = i;
    410                 idx++;
     470                pMappings[idx].root      = i;
    411471            }
    412             cMappings++;
     472            idx++;
    413473        }
    414474    }
     
    416476    /* Return actual number of mappings, regardless whether the handed in
    417477     * 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;
    422488}
    423489
     
    437503int vbsfMappingsQueryName(PSHFLCLIENTDATA pClient, SHFLROOT root, SHFLSTRING *pString)
    438504{
    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;
    444508    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            }
    464532        }
    465533        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;
    471535    }
    472536    else
    473         rc = VERR_FILE_NOT_FOUND;
     537        rc = VERR_INVALID_PARAMETER;
    474538
    475539    LogFlow(("vbsfMappingsQuery:Name return rc = %Rrc\n", rc));
    476 
    477540    return rc;
    478541}
     
    540603    return rc;
    541604}
     605
     606/**
     607 * Implements SHFL_FN_QUERY_MAP_INFO.
     608 * @since VBox 6.0
     609 */
     610int 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
    542663
    543664#ifdef UNITTEST
     
    662783    return rc;
    663784}
     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 */
     803int 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 */
     860int 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 */
     886static 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  
    3838    bool        fPlaceholder;           /**< Mapping does not exist in the VM settings but the guest
    3939                                             still has. fMissing is always true for this mapping. */
     40    bool        fLoadedRootId;          /**< Set if vbsfMappingLoaded has found this mapping already. */
    4041} MAPPING;
    4142/** Pointer to a MAPPING structure. */
     
    5051int vbsfMappingsRemove(PSHFLSTRING pMapName);
    5152
    52 int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, PSHFLMAPPING pMappings, uint32_t *pcMappings);
     53int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, bool fOnlyAutoMounts, PSHFLMAPPING pMappings, uint32_t *pcMappings);
    5354int vbsfMappingsQueryName(PSHFLCLIENTDATA pClient, SHFLROOT root, SHFLSTRING *pString);
    5455int vbsfMappingsQueryWritable(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fWritable);
    5556int vbsfMappingsQueryAutoMount(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fAutoMount);
    5657int vbsfMappingsQuerySymlinksCreate(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fSymlinksCreate);
     58int vbsfMappingsQueryInfo(PSHFLCLIENTDATA pClient, SHFLROOT root, PSHFLSTRING pNameBuf, PSHFLSTRING pMntPtBuf,
     59                          uint64_t *pfFlags, uint32_t *puVersion);
    5760
    5861int vbsfMapFolder(PSHFLCLIENTDATA pClient, PSHFLSTRING pszMapName, RTUTF16 delimiter,
    5962                  bool fCaseSensitive, SHFLROOT *pRoot);
    6063int vbsfUnmapFolder(PSHFLCLIENTDATA pClient, SHFLROOT root);
     64
     65int vbsfMappingsWaitForChanges(PSHFLCLIENTDATA pClient, VBOXHGCMCALLHANDLE hCall, PVBOXHGCMSVCPARM pParm, bool fRestored);
     66int vbsfMappingsCancelChangesWaits(PSHFLCLIENTDATA pClient);
    6167
    6268const char* vbsfMappingsQueryHostRoot(SHFLROOT root);
     
    6571bool vbsfIsHostMappingCaseSensitive(SHFLROOT root);
    6672
    67 int vbsfMappingLoaded(const PMAPPING pLoadedMapping, SHFLROOT root);
     73int vbsfMappingLoaded(MAPPING const *pLoadedMapping, SHFLROOT root);
    6874PMAPPING vbsfMappingGetByRoot(SHFLROOT root);
    6975
  • trunk/src/VBox/HostServices/SharedFolders/service.cpp

    r75380 r75407  
    2626#include <iprt/string.h>
    2727#include <iprt/assert.h>
     28#include <VBox/AssertGuest.h>
    2829#include <VBox/vmm/ssm.h>
    2930#include <VBox/vmm/pdmifs.h>
     
    237238                rc = SSMR3GetMem(pSSM, pFolderName, cb);
    238239                AssertRCReturn(rc, rc);
    239                 AssertReturn(pFolderName->u16Length < cb && pFolderName->u16Size < pFolderName->u16Length,
     240                AssertReturn(pFolderName->u16Size < cb && pFolderName->u16Length < pFolderName->u16Size,
    240241                             SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    241242                                               "Bad folder name string: %#x/%#x cb=%#x\n",
     
    267268            rc = SSMR3GetMem(pSSM, pMapName, cb);
    268269            AssertRCReturn(rc, rc);
    269             AssertReturn(pMapName->u16Length < cb && pMapName->u16Size < pMapName->u16Length,
     270            AssertReturn(pMapName->u16Size < cb && pMapName->u16Length < pMapName->u16Size,
    270271                         SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    271272                                           "Bad map name string: %#x/%#x cb=%#x\n",
     
    293294                rc = SSMR3GetMem(pSSM, pAutoMountPoint, cb);
    294295                AssertRCReturn(rc, rc);
    295                 AssertReturn(pAutoMountPoint->u16Length < cb && pAutoMountPoint->u16Size < pAutoMountPoint->u16Length,
     296                AssertReturn(pAutoMountPoint->u16Size < cb && pAutoMountPoint->u16Length < pAutoMountPoint->u16Size,
    296297                             SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
    297298                                               "Bad auto mount point string: %#x/%#x cb=%#x\n",
     
    331332}
    332333
    333 static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     334static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
     335                                   void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    334336{
    335337    RT_NOREF1(u32ClientID);
     
    388390                    if (fu32Flags & SHFL_MF_UTF8)
    389391                        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);
    394399                    if (RT_SUCCESS(rc))
    395400                    {
     
    12951300        }
    12961301
     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
    12971354        default:
    12981355        {
  • trunk/src/VBox/HostServices/SharedFolders/shfl.h

    r69500 r75407  
    4343#define SHFL_CF_SYMLINKS         (0x00000008)
    4444
     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
    4549/** @} */
    4650
  • trunk/src/VBox/HostServices/SharedFolders/vbsf.h

    r69500 r75407  
     1/* $Id$ */
    12/** @file
    23 * VBox Shared Folders header.
     
    1516 */
    1617
    17 #ifndef __VBSF__H
    18 #define __VBSF__H
     18#ifndef ___vbsf_h___
     19#define ___vbsf_h___
    1920
    2021#include "shfl.h"
     
    4142int vbsfSymlink(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pNewPath, SHFLSTRING *pOldPath, SHFLFSOBJINFO *pInfo);
    4243
    43 #endif /* __VBSF__H */
     44#endif /* !___vbsf_h___ */
     45
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette