VirtualBox

Changeset 14852 in vbox


Ignore:
Timestamp:
Dec 1, 2008 11:46:18 AM (16 years ago)
Author:
vboxsync
Message:

#3162: Plugin backends are now loaded upon startup, this should get rid of most memory leaks as most structures are now static.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxHDD-new.h

    r14816 r14852  
    10491049{
    10501050    /** Name of the backend. */
    1051     char *pszBackend;
     1051    const char *pszBackend;
    10521052    /** Capabilities of the backend (a combination of the VD_CAP_* flags). */
    10531053    uint64_t uBackendCaps;
     
    10721072typedef VBOXHDD *PVBOXHDD;
    10731073
     1074/**
     1075 * Initializes HDD backends.
     1076 *
     1077 * @returns VBox status code.
     1078 */
     1079VBOXDDU_DECL(int) VDInit();
     1080
     1081/**
     1082 * Destroys loaded HDD backends.
     1083 *
     1084 * @returns VBox status code.
     1085 */
     1086VBOXDDU_DECL(int) VDShutdown();
    10741087
    10751088/**
  • trunk/src/VBox/Devices/Storage/RawHDDCore.cpp

    r13580 r14852  
    10901090    /* paConfigInfo */
    10911091    NULL,
     1092    /* hPlugin */
     1093    NIL_RTLDRMOD,
    10921094    /* pfnCheckIfValid */
    10931095    rawCheckIfValid,
  • trunk/src/VBox/Devices/Storage/VBoxHDD-new.cpp

    r14350 r14852  
    6767    unsigned        uOpenFlags;
    6868
    69     /** Handle for the shared object / DLL. */
    70     RTLDRMOD            hPlugin;
    7169    /** Function pointers for the various backend methods. */
    7270    PCVBOXHDDBACKEND    Backend;
     
    129127#endif
    130128
    131 static PCVBOXHDDBACKEND aBackends[] =
     129static unsigned g_cBackends = 0;
     130static PVBOXHDDBACKEND *g_apBackends = NULL;
     131static PVBOXHDDBACKEND aStaticBackends[] =
    132132{
    133133    &g_RawBackend,
    134134    &g_VmdkBackend,
    135135    &g_VDIBackend,
    136     &g_VhdBackend,
     136    &g_VhdBackend
    137137#ifdef VBOX_WITH_ISCSI
    138     &g_ISCSIBackend,
     138    ,&g_ISCSIBackend
    139139#endif
    140     NULL
    141140};
    142141
     142/**
     143 * internal: add several backends.
     144 */
     145static int vdAddBackends(PVBOXHDDBACKEND *ppBackends, unsigned cBackends)
     146{
     147    PVBOXHDDBACKEND *pTmp = (PVBOXHDDBACKEND*)RTMemRealloc(g_apBackends,
     148           (g_cBackends + cBackends) * sizeof(PVBOXHDDBACKEND));
     149    if (RT_UNLIKELY(!pTmp))
     150        return VERR_NO_MEMORY;
     151    g_apBackends = pTmp;
     152    memcpy(&g_apBackends[g_cBackends], ppBackends, cBackends * sizeof(PVBOXHDDBACKEND));
     153    g_cBackends += cBackends;
     154    return VINF_SUCCESS;
     155}
     156
     157/**
     158 * internal: add single backend.
     159 */
     160DECLINLINE(int) vdAddBackend(PVBOXHDDBACKEND pBackend)
     161{
     162    return vdAddBackends(&pBackend, 1);
     163}
    143164
    144165/**
     
    159180 * internal: find image format backend.
    160181 */
    161 static int vdFindBackend(const char *pszBackend, PCVBOXHDDBACKEND *ppBackend,
    162                          RTLDRMOD *phPlugin)
     182static int vdFindBackend(const char *pszBackend, PCVBOXHDDBACKEND *ppBackend)
    163183{
    164184    int rc = VINF_SUCCESS;
    165185    PCVBOXHDDBACKEND pBackend = NULL;
    166     RTLDRMOD hPlugin = NIL_RTLDRMOD;
    167 
    168     for (unsigned i = 0; aBackends[i] != NULL; i++)
    169     {
    170         if (!strcmp(pszBackend, aBackends[i]->pszBackendName))
    171         {
    172             pBackend = aBackends[i];
     186
     187    if (!g_apBackends)
     188        VDInit();
     189
     190    for (unsigned i = 0; i < g_cBackends; i++)
     191    {
     192        if (!strcmp(pszBackend, g_apBackends[i]->pszBackendName))
     193        {
     194            pBackend = g_apBackends[i];
    173195            break;
    174196        }
    175197    }
    176 
    177     /* If no static backend is found try loading a shared module with
    178      * pszBackend as filename. */
    179     if (!pBackend)
    180     {
    181         char szSharedLibPath[RTPATH_MAX];
    182         char *pszPluginName;
    183 
    184         rc = RTPathAppPrivateArch(szSharedLibPath, sizeof(szSharedLibPath));
    185         if (RT_FAILURE(rc))
    186             return rc;
    187 
    188         /* HDD Format Plugins have VBoxHDD as prefix, prepend it. */
    189         RTStrAPrintf(&pszPluginName, "%s/%s%s",
    190                      szSharedLibPath, VBOX_HDDFORMAT_PLUGIN_PREFIX, pszBackend);
    191         if (!pszPluginName)
    192         {
    193             rc = VERR_NO_MEMORY;
    194             goto out;
    195         }
    196 
    197         /* Try to load the plugin (RTLdrLoad takes care of the suffix). */
    198         rc = SUPR3HardenedLdrLoad(pszPluginName, &hPlugin);
    199         if (RT_SUCCESS(rc))
    200         {
    201             PFNVBOXHDDFORMATLOAD pfnHDDFormatLoad;
    202 
    203             rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME,
    204                                 (void**)&pfnHDDFormatLoad);
    205             if (RT_FAILURE(rc) || !pfnHDDFormatLoad)
    206             {
    207                 LogFunc(("error resolving the entry point %s in plugin %s, rc=%Rrc, pfnHDDFormat=%#p\n", VBOX_HDDFORMAT_LOAD_NAME, pszPluginName, rc, pfnHDDFormatLoad));
    208                 if (RT_SUCCESS(rc))
    209                     rc = VERR_SYMBOL_NOT_FOUND;
    210                 goto out;
    211             }
    212 
    213             /* Get the function table. */
    214             PVBOXHDDBACKEND pBE;
    215             rc = pfnHDDFormatLoad(&pBE);
    216             if (RT_FAILURE(rc))
    217                 goto out;
    218             /* Check if the sizes match. If not this plugin is too old. */
    219             if (pBE->cbSize != sizeof(VBOXHDDBACKEND))
    220             {
    221                 rc = VERR_VDI_UNSUPPORTED_VERSION;
    222                 goto out;
    223             }
    224             pBackend = pBE;
    225         }
    226         else
    227         {
    228             /* If the backend plugin doesn't exist, don't treat this as an
    229              * error. Just return the NULL pointers. */
    230             rc = VINF_SUCCESS;
    231         }
    232 
    233         RTStrFree(pszPluginName);
    234     }
    235 
    236 out:
    237     if (RT_FAILURE(rc))
    238     {
    239         if (hPlugin != NIL_RTLDRMOD)
    240             RTLdrClose(hPlugin);
    241         hPlugin = NIL_RTLDRMOD;
    242         pBackend = NULL;
    243     }
    244 
    245198    *ppBackend = pBackend;
    246     *phPlugin = hPlugin;
    247199    return rc;
    248200}
     
    614566
    615567/**
     568 * internal: scans plugin directory and loads the backends have been found.
     569 */
     570static int vdLoadDynamicBackends()
     571{
     572    int rc = VINF_SUCCESS;
     573    PRTDIR pPluginDir = NULL;
     574
     575    /* Enumerate plugin backends. */
     576    char szPath[RTPATH_MAX];
     577    rc = RTPathAppPrivateArch(szPath, sizeof(szPath));
     578    if (RT_FAILURE(rc))
     579        return rc;
     580
     581    /* To get all entries with VBoxHDD as prefix. */
     582    char *pszPluginFilter;
     583    rc = RTStrAPrintf(&pszPluginFilter, "%s/%s*", szPath,
     584            VBOX_HDDFORMAT_PLUGIN_PREFIX);
     585    if (RT_FAILURE(rc))
     586    {
     587        rc = VERR_NO_MEMORY;
     588        return rc;
     589    }
     590
     591    PRTDIRENTRYEX pPluginDirEntry = NULL;
     592    size_t cbPluginDirEntry = sizeof(RTDIRENTRYEX);
     593    /* The plugins are in the same directory as the other shared libs. */
     594    rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT);
     595    if (RT_FAILURE(rc))
     596    {
     597        /* On Windows the above immediately signals that there are no
     598         * files matching, while on other platforms enumerating the
     599         * files below fails. Either way: no plugins. */
     600        goto out;
     601    }
     602
     603    pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(sizeof(RTDIRENTRYEX));
     604    if (!pPluginDirEntry)
     605    {
     606        rc = VERR_NO_MEMORY;
     607        goto out;
     608    }
     609
     610    while ((rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING)) != VERR_NO_MORE_FILES)
     611    {
     612        RTLDRMOD hPlugin = NIL_RTLDRMOD;
     613        PFNVBOXHDDFORMATLOAD pfnHDDFormatLoad = NULL;
     614        PVBOXHDDBACKEND pBackend = NULL;
     615        char *pszPluginPath = NULL;
     616
     617        if (rc == VERR_BUFFER_OVERFLOW)
     618        {
     619            /* allocate new buffer. */
     620            RTMemFree(pPluginDirEntry);
     621            pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(cbPluginDirEntry);
     622            /* Retry. */
     623            rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING);
     624            if (RT_FAILURE(rc))
     625                break;
     626        }
     627        else if (RT_FAILURE(rc))
     628            break;
     629
     630        /* We got the new entry. */
     631        if (!RTFS_IS_FILE(pPluginDirEntry->Info.Attr.fMode))
     632            continue;
     633
     634        /* Prepend the path to the libraries. */
     635        rc = RTStrAPrintf(&pszPluginPath, "%s/%s", szPath, pPluginDirEntry->szName);
     636        if (RT_FAILURE(rc))
     637        {
     638            rc = VERR_NO_MEMORY;
     639            break;
     640        }
     641
     642        rc = SUPR3HardenedLdrLoad(pszPluginPath, &hPlugin);
     643        if (RT_SUCCESS(rc))
     644        {
     645            rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, (void**)&pfnHDDFormatLoad);
     646            if (RT_FAILURE(rc) || !pfnHDDFormatLoad)
     647            {
     648                LogFunc(("error resolving the entry point %s in plugin %s, rc=%Rrc, pfnHDDFormat=%#p\n", VBOX_HDDFORMAT_LOAD_NAME, pPluginDirEntry->szName, rc, pfnHDDFormatLoad));
     649                if (RT_SUCCESS(rc))
     650                    rc = VERR_SYMBOL_NOT_FOUND;
     651            }
     652
     653            if (RT_SUCCESS(rc))
     654            {
     655                /* Get the function table. */
     656                rc = pfnHDDFormatLoad(&pBackend);
     657                if (RT_SUCCESS(rc) && pBackend->cbSize == sizeof(VBOXHDDBACKEND))
     658                {
     659                    pBackend->hPlugin = hPlugin;
     660                    vdAddBackend(pBackend);
     661                }
     662                else
     663                    LogFunc(("ignored plugin '%s': pBackend->cbSize=%d rc=%Rrc\n", pszPluginPath, pBackend->cbSize, rc));
     664            }
     665            else
     666                LogFunc(("ignored plugin '%s': rc=%Rrc\n", pszPluginPath, rc));
     667
     668            if (RT_FAILURE(rc))
     669                RTLdrClose(hPlugin);
     670        }
     671        RTStrFree(pszPluginPath);
     672    }
     673out:
     674    if (rc == VERR_NO_MORE_FILES)
     675        rc = VINF_SUCCESS;
     676    RTStrFree(pszPluginFilter);
     677    if (pPluginDirEntry)
     678        RTMemFree(pPluginDirEntry);
     679    if (pPluginDir)
     680        RTDirClose(pPluginDir);
     681    return rc;
     682}
     683
     684/**
     685 * Initializes HDD backends.
     686 *
     687 * @returns VBox status code.
     688 */
     689VBOXDDU_DECL(int) VDInit()
     690{
     691    int rc = vdAddBackends(aStaticBackends, RT_ELEMENTS(aStaticBackends));
     692    if (RT_SUCCESS(rc))
     693        rc = vdLoadDynamicBackends();
     694    LogRel(("VDInit finished\n"));
     695    return rc;
     696}
     697
     698/**
     699 * Destroys loaded HDD backends.
     700 *
     701 * @returns VBox status code.
     702 */
     703VBOXDDU_DECL(int) VDShutdown()
     704{
     705    PVBOXHDDBACKEND *pBackends = g_apBackends;
     706    unsigned cBackends = g_cBackends;
     707
     708    if (!pBackends)
     709        return VERR_INTERNAL_ERROR;
     710
     711    g_cBackends = 0;
     712    g_apBackends = NULL;
     713
     714    for (unsigned i = 0; i < cBackends; i++)
     715        if (pBackends[i]->hPlugin != NIL_RTLDRMOD)
     716            RTLdrClose(pBackends[i]->hPlugin);
     717    return VINF_SUCCESS;
     718}
     719
     720
     721
     722/**
    616723 * Lists all HDD backends and their capabilities in a caller-provided buffer.
    617724 *
     
    633740
    634741    LogFlowFunc(("cEntriesAlloc=%u pEntries=%#p pcEntriesUsed=%#p\n", cEntriesAlloc, pEntries, pcEntriesUsed));
    635     do
    636     {
    637         /* Check arguments. */
    638         AssertMsgBreakStmt(cEntriesAlloc,
    639                            ("cEntriesAlloc=%u\n", cEntriesAlloc),
    640                            rc = VERR_INVALID_PARAMETER);
    641         AssertMsgBreakStmt(VALID_PTR(pEntries),
    642                            ("pEntries=%#p\n", pEntries),
    643                            rc = VERR_INVALID_PARAMETER);
    644         AssertMsgBreakStmt(VALID_PTR(pcEntriesUsed),
    645                            ("pcEntriesUsed=%#p\n", pcEntriesUsed),
    646                            rc = VERR_INVALID_PARAMETER);
    647 
    648         /* First enumerate static backends. */
    649         for (unsigned i = 0; aBackends[i] != NULL; i++)
    650         {
    651             char *pszName = RTStrDup(aBackends[i]->pszBackendName);
    652             if (!pszName)
    653             {
    654                 rc = VERR_NO_MEMORY;
    655                 break;
    656             }
    657             pEntries[cEntries].pszBackend = pszName;
    658             pEntries[cEntries].uBackendCaps = aBackends[i]->uBackendCaps;
    659             pEntries[cEntries].papszFileExtensions = aBackends[i]->papszFileExtensions;
    660             pEntries[cEntries].paConfigInfo = aBackends[i]->paConfigInfo;
    661             cEntries++;
    662             if (cEntries >= cEntriesAlloc)
    663             {
    664                 rc = VERR_BUFFER_OVERFLOW;
    665                 break;
    666             }
    667         }
    668         if (RT_FAILURE(rc))
    669             break;
    670 
    671         /* Then enumerate plugin backends. */
    672         char szPath[RTPATH_MAX];
    673         rc = RTPathAppPrivateArch(szPath, sizeof(szPath));
    674         if (RT_FAILURE(rc))
    675             break;
    676 
    677         /* To get all entries with VBoxHDD as prefix. */
    678         char *pszPluginFilter;
    679         rc = RTStrAPrintf(&pszPluginFilter, "%s/%s*", szPath,
    680                           VBOX_HDDFORMAT_PLUGIN_PREFIX);
    681         if (RT_FAILURE(rc))
    682         {
    683             rc = VERR_NO_MEMORY;
    684             break;
    685         }
    686 
    687         /* The plugins are in the same directory as the other shared libs. */
    688         rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT);
    689         if (RT_FAILURE(rc))
    690         {
    691             /* On Windows the above immediately signals that there are no
    692              * files matching, while on other platforms enumerating the
    693              * files below fails. Either way: no plugins. */
    694             break;
    695         }
    696 
    697         PRTDIRENTRYEX pPluginDirEntry = NULL;
    698         size_t cbPluginDirEntry = sizeof(RTDIRENTRY);
    699         pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(sizeof(RTDIRENTRY));
    700         if (!pPluginDirEntry)
    701         {
    702             rc = VERR_NO_MEMORY;
    703             break;
    704         }
    705 
    706         while ((rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING)) != VERR_NO_MORE_FILES)
    707         {
    708             RTLDRMOD hPlugin = NIL_RTLDRMOD;
    709             PFNVBOXHDDFORMATLOAD pfnHDDFormatLoad = NULL;
    710             PVBOXHDDBACKEND pBackend = NULL;
    711             char *pszPluginPath = NULL;
    712 
    713             if (rc == VERR_BUFFER_OVERFLOW)
    714             {
    715                 /* allocate new buffer. */
    716                 RTMemFree(pPluginDirEntry);
    717                 pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(cbPluginDirEntry);
    718                 /* Retry. */
    719                 rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING);
    720                 if (RT_FAILURE(rc))
    721                     break;
    722             }
    723             else if (RT_FAILURE(rc))
    724                 break;
    725 
    726             /* We got the new entry. */
    727             if (!RTFS_IS_FILE(pPluginDirEntry->Info.Attr.fMode))
    728                 continue;
    729 
    730             /* Prepend the path to the libraries. */
    731             rc = RTStrAPrintf(&pszPluginPath, "%s/%s", szPath, pPluginDirEntry->szName);
    732             if (RT_FAILURE(rc))
    733             {
    734                 rc = VERR_NO_MEMORY;
    735                 break;
    736             }
    737 
    738             rc = SUPR3HardenedLdrLoad(pszPluginPath, &hPlugin);
    739             if (RT_SUCCESS(rc))
    740             {
    741                 rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, (void**)&pfnHDDFormatLoad);
    742                 if (RT_FAILURE(rc) || !pfnHDDFormatLoad)
    743                 {
    744                     LogFunc(("error resolving the entry point %s in plugin %s, rc=%Rrc, pfnHDDFormat=%#p\n", VBOX_HDDFORMAT_LOAD_NAME, pPluginDirEntry->szName, rc, pfnHDDFormatLoad));
    745                     if (RT_SUCCESS(rc))
    746                         rc = VERR_SYMBOL_NOT_FOUND;
    747                 }
    748 
    749                 if (RT_SUCCESS(rc))
    750                 {
    751                     /* Get the function table. */
    752                     rc = pfnHDDFormatLoad(&pBackend);
    753                     if (RT_SUCCESS(rc) && pBackend->cbSize == sizeof(VBOXHDDBACKEND))
    754                     {
    755                         char *pszName = RTStrDup(pBackend->pszBackendName);
    756                         if (!pszName)
    757                         {
    758                             rc = VERR_NO_MEMORY;
    759                             break;
    760                         }
    761                         pEntries[cEntries].pszBackend = pszName;
    762                         pEntries[cEntries].uBackendCaps = pBackend->uBackendCaps;
    763                         unsigned cExts, iExt;
    764                         for (cExts=0; pBackend->papszFileExtensions[cExts]; cExts++)
    765                             ;
    766                         const char **paExts = (const char **)RTMemAlloc((cExts+1) * sizeof(paExts[0])); /** @todo rainy day: fix leak on error. */
    767                         if (!paExts)
    768                         {
    769                             rc = VERR_NO_MEMORY;
    770                             break;
    771                         }
    772                         for (iExt=0; iExt < cExts; iExt++)
    773                         {
    774                             paExts[iExt] = (const char*)RTStrDup(pBackend->papszFileExtensions[iExt]);
    775                             if (!paExts[iExt])
    776                             {
    777                                 rc = VERR_NO_MEMORY;
    778                                 break;
    779                             }
    780                         }
    781                         paExts[iExt] = NULL;
    782                         pEntries[cEntries].papszFileExtensions = paExts;
    783                         if (pBackend->paConfigInfo != NULL)
    784                         {
    785                             /* copy the whole config field! */
    786                             rc = VERR_NOT_IMPLEMENTED;
    787                             break;
    788                         }
    789                         pEntries[cEntries].paConfigInfo = NULL;
    790                         cEntries++;
    791                         if (cEntries >= cEntriesAlloc)
    792                         {
    793                             rc = VERR_BUFFER_OVERFLOW;
    794                             break;
    795                         }
    796                     }
    797                     else
    798                         LogFunc(("ignored plugin '%s': pBackend->cbSize=%d rc=%Rrc\n", pszPluginPath, pBackend->cbSize, rc));
    799                 }
    800                 else
    801                     LogFunc(("ignored plugin '%s': rc=%Rrc\n", pszPluginPath, rc));
    802 
    803                 RTLdrClose(hPlugin);
    804             }
    805             RTStrFree(pszPluginPath);
    806         }
    807         if (rc == VERR_NO_MORE_FILES)
    808             rc = VINF_SUCCESS;
    809         RTStrFree(pszPluginFilter);
    810         if (pPluginDirEntry)
    811             RTMemFree(pPluginDirEntry);
    812         if (pPluginDir)
    813             RTDirClose(pPluginDir);
    814     } while (0);
    815     /* Ignore any files which can't be found. Happens e.g. on Windows when
    816      * absolutely no plugins are installed (see above). Totally harmless. */
    817     if (rc == VERR_FILE_NOT_FOUND)
    818         rc = VINF_SUCCESS;
     742    /* Check arguments. */
     743    AssertMsgReturn(cEntriesAlloc,
     744                    ("cEntriesAlloc=%u\n", cEntriesAlloc),
     745                    VERR_INVALID_PARAMETER);
     746    AssertMsgReturn(VALID_PTR(pEntries),
     747                    ("pEntries=%#p\n", pEntries),
     748                    VERR_INVALID_PARAMETER);
     749    AssertMsgReturn(VALID_PTR(pcEntriesUsed),
     750                    ("pcEntriesUsed=%#p\n", pcEntriesUsed),
     751                    VERR_INVALID_PARAMETER);
     752    if (!g_apBackends)
     753        VDInit();
     754
     755    if (cEntriesAlloc < g_cBackends)
     756    {
     757        *pcEntriesUsed = g_cBackends;
     758        return VERR_BUFFER_OVERFLOW;
     759    }
     760
     761     for (unsigned i = 0; i < g_cBackends; i++)
     762     {
     763         pEntries[i].pszBackend = g_apBackends[i]->pszBackendName;
     764         pEntries[i].uBackendCaps = g_apBackends[i]->uBackendCaps;
     765         pEntries[i].papszFileExtensions = g_apBackends[i]->papszFileExtensions;
     766         pEntries[i].paConfigInfo = g_apBackends[i]->paConfigInfo;
     767     }
    819768
    820769    LogFlowFunc(("returns %Rrc *pcEntriesUsed=%u\n", rc, cEntries));
    821     *pcEntriesUsed = cEntries;
     770    *pcEntriesUsed = g_cBackends;
    822771    return rc;
    823772}
     
    833782VBOXDDU_DECL(int) VDBackendInfoOne(const char *pszBackend, PVDBACKENDINFO pEntry)
    834783{
    835     return VERR_NOT_IMPLEMENTED;
     784    LogFlowFunc(("pszBackend=%#p pEntry=%#p\n", pszBackend, pEntry));
     785    /* Check arguments. */
     786    AssertMsgReturn(VALID_PTR(pszBackend),
     787                    ("pszBackend=%#p\n", pszBackend),
     788                    VERR_INVALID_PARAMETER);
     789    AssertMsgReturn(VALID_PTR(pEntry),
     790                    ("pEntry=%#p\n", pEntry),
     791                    VERR_INVALID_PARAMETER);
     792    if (!g_apBackends)
     793        VDInit();
     794
     795    /* Go through loaded backends. */
     796    for (unsigned i = 0; i < g_cBackends; i++)
     797    {
     798        if (!strcmp(pszBackend, g_apBackends[i]->pszBackendName))
     799        {
     800            pEntry->pszBackend = g_apBackends[i]->pszBackendName;
     801            pEntry->uBackendCaps = g_apBackends[i]->uBackendCaps;
     802            pEntry->papszFileExtensions = g_apBackends[i]->papszFileExtensions;
     803            pEntry->paConfigInfo = g_apBackends[i]->paConfigInfo;
     804            return VINF_SUCCESS;
     805        }
     806    }
     807
     808    return VERR_NOT_FOUND;
    836809}
    837810
     
    924897VBOXDDU_DECL(int) VDGetFormat(const char *pszFilename, char **ppszFormat)
    925898{
    926     PRTDIR pPluginDir = NULL;
    927899    int rc = VERR_NOT_SUPPORTED;
    928     bool fPluginFound = false;
    929900
    930901    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
    931     do
    932     {
    933         /* Check arguments. */
    934         AssertMsgBreakStmt(VALID_PTR(pszFilename) && *pszFilename,
    935                            ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename),
    936                            rc = VERR_INVALID_PARAMETER);
    937         AssertMsgBreakStmt(VALID_PTR(ppszFormat),
    938                            ("ppszFormat=%#p\n", ppszFormat),
    939                            rc = VERR_INVALID_PARAMETER);
    940 
    941         /* First check if static backends support this file format. */
    942         for (unsigned i = 0; aBackends[i] != NULL; i++)
    943         {
    944             if (aBackends[i]->pfnCheckIfValid)
     902    /* Check arguments. */
     903    AssertMsgReturn(VALID_PTR(pszFilename) && *pszFilename,
     904                    ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename),
     905                    VERR_INVALID_PARAMETER);
     906    AssertMsgReturn(VALID_PTR(ppszFormat),
     907                    ("ppszFormat=%#p\n", ppszFormat),
     908                    VERR_INVALID_PARAMETER);
     909
     910    if (!g_apBackends)
     911        VDInit();
     912
     913    /* Find the backend supporting this file format. */
     914    for (unsigned i = 0; i < g_cBackends; i++)
     915    {
     916        if (g_apBackends[i]->pfnCheckIfValid)
     917        {
     918            rc = g_apBackends[i]->pfnCheckIfValid(pszFilename);
     919            if (RT_SUCCESS(rc))
    945920            {
    946                 rc = aBackends[i]->pfnCheckIfValid(pszFilename);
    947                 if (RT_SUCCESS(rc))
     921                /* Copy the name into the new string. */
     922                char *pszFormat = RTStrDup(g_apBackends[i]->pszBackendName);
     923                if (!pszFormat)
    948924                {
    949                     fPluginFound = true;
    950                     /* Copy the name into the new string. */
    951                     char *pszFormat = RTStrDup(aBackends[i]->pszBackendName);
    952                     if (!pszFormat)
    953                     {
    954                         rc = VERR_NO_MEMORY;
    955                         break;
    956                     }
    957                     *ppszFormat = pszFormat;
     925                    rc = VERR_NO_MEMORY;
    958926                    break;
    959927                }
    960             }
    961         }
    962         if (fPluginFound)
    963             break;
    964 
    965         /* Then check if plugin backends support this file format. */
    966         char szPath[RTPATH_MAX];
    967         rc = RTPathAppPrivateArch(szPath, sizeof(szPath));
    968         if (RT_FAILURE(rc))
    969             break;
    970 
    971         /* To get all entries with VBoxHDD as prefix. */
    972         char *pszPluginFilter;
    973         rc = RTStrAPrintf(&pszPluginFilter, "%s/%s*", szPath,
    974                           VBOX_HDDFORMAT_PLUGIN_PREFIX);
    975         if (RT_FAILURE(rc))
    976         {
    977             rc = VERR_NO_MEMORY;
    978             break;
    979         }
    980 
    981         /* The plugins are in the same directory as the other shared libs. */
    982         rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT);
    983         if (RT_FAILURE(rc))
    984         {
    985             if (rc == VERR_FILE_NOT_FOUND)
    986             {
    987                 /* VERR_FILE_NOT_FOUND would be interpreted as the hard
    988                  * disk storage unit was not found, so replace with
    989                  * VERR_NOT_SUPPORTED which is more meaningful in this case */
    990                 rc = VERR_NOT_SUPPORTED;
    991             }
    992             break;
    993         }
    994 
    995         PRTDIRENTRYEX pPluginDirEntry = NULL;
    996         size_t cbPluginDirEntry = sizeof(RTDIRENTRY);
    997         pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(sizeof(RTDIRENTRY));
    998         if (!pPluginDirEntry)
    999         {
    1000             rc = VERR_NO_MEMORY;
    1001             break;
    1002         }
    1003 
    1004         while ((rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING)) != VERR_NO_MORE_FILES)
    1005         {
    1006             RTLDRMOD hPlugin = NIL_RTLDRMOD;
    1007             PFNVBOXHDDFORMATLOAD pfnHDDFormatLoad = NULL;
    1008             PVBOXHDDBACKEND pBackend = NULL;
    1009             char *pszPluginPath = NULL;
    1010 
    1011             if (rc == VERR_BUFFER_OVERFLOW)
    1012             {
    1013                 /* allocate new buffer. */
    1014                 RTMemFree(pPluginDirEntry);
    1015                 pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(cbPluginDirEntry);
    1016                 /* Retry. */
    1017                 rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING);
    1018                 if (RT_FAILURE(rc))
    1019                     break;
    1020             }
    1021             else if (RT_FAILURE(rc))
    1022                 break;
    1023 
    1024             /* We got the new entry. */
    1025             if (!RTFS_IS_FILE(pPluginDirEntry->Info.Attr.fMode))
    1026                 continue;
    1027 
    1028             /* Prepend the path to the libraries. */
    1029             rc = RTStrAPrintf(&pszPluginPath, "%s/%s", szPath, pPluginDirEntry->szName);
    1030             if (RT_FAILURE(rc))
    1031             {
    1032                 rc = VERR_NO_MEMORY;
     928                *ppszFormat = pszFormat;
     929                rc = VINF_SUCCESS;
    1033930                break;
    1034931            }
    1035 
    1036             rc = SUPR3HardenedLdrLoad(pszPluginPath, &hPlugin);
    1037             if (RT_SUCCESS(rc))
    1038             {
    1039                 rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, (void**)&pfnHDDFormatLoad);
    1040                 if (RT_FAILURE(rc) || !pfnHDDFormatLoad)
    1041                 {
    1042                     LogFunc(("error resolving the entry point %s in plugin %s, rc=%Rrc, pfnHDDFormat=%#p\n", VBOX_HDDFORMAT_LOAD_NAME, pPluginDirEntry->szName, rc, pfnHDDFormatLoad));
    1043                     if (RT_SUCCESS(rc))
    1044                         rc = VERR_SYMBOL_NOT_FOUND;
    1045                 }
    1046 
    1047                 if (RT_SUCCESS(rc))
    1048                 {
    1049                     /* Get the function table. */
    1050                     rc = pfnHDDFormatLoad(&pBackend);
    1051                     if (RT_SUCCESS(rc) && pBackend->cbSize == sizeof(VBOXHDDBACKEND))
    1052                     {
    1053 
    1054                         /* Check if the plugin can handle this file. */
    1055                         rc = pBackend->pfnCheckIfValid(pszFilename);
    1056                         if (RT_SUCCESS(rc))
    1057                         {
    1058                             fPluginFound = true;
    1059                             rc = VINF_SUCCESS;
    1060 
    1061                             /* Report the format name. */
    1062                             RTPathStripExt(pPluginDirEntry->szName);
    1063                             AssertBreakStmt(strlen(pPluginDirEntry->szName) > VBOX_HDDFORMAT_PLUGIN_PREFIX_LENGTH,
    1064                                             rc = VERR_INVALID_NAME);
    1065 
    1066                             char *pszFormat = NULL;
    1067                             pszFormat = RTStrDup(pPluginDirEntry->szName + VBOX_HDDFORMAT_PLUGIN_PREFIX_LENGTH);
    1068                             if (!pszFormat)
    1069                                 rc = VERR_NO_MEMORY;
    1070 
    1071                             *ppszFormat = pszFormat;
    1072                         }
    1073                     }
    1074                 }
    1075                 else
    1076                     pBackend = NULL;
    1077 
    1078                 RTLdrClose(hPlugin);
    1079             }
    1080             RTStrFree(pszPluginPath);
    1081 
    1082             /*
    1083              * We take the first plugin which can handle this file.
    1084              */
    1085             if (fPluginFound)
    1086                 break;
    1087         }
    1088         if (rc == VERR_NO_MORE_FILES)
    1089             rc = VERR_NOT_SUPPORTED;
    1090 
    1091         RTStrFree(pszPluginFilter);
    1092         if (pPluginDirEntry)
    1093             RTMemFree(pPluginDirEntry);
    1094         if (pPluginDir)
    1095             RTDirClose(pPluginDir);
    1096     } while (0);
     932        }
     933    }
    1097934
    1098935    LogFlowFunc(("returns %Rrc *ppszFormat=\"%s\"\n", rc, *ppszFormat));
     
    1161998        pImage->pVDIfsImage = pVDIfsImage;
    1162999
    1163         rc = vdFindBackend(pszBackend, &pImage->Backend, &pImage->hPlugin);
     1000        rc = vdFindBackend(pszBackend, &pImage->Backend);
    11641001        if (RT_FAILURE(rc))
    11651002            break;
     
    13131150        if (pImage)
    13141151        {
    1315             if (pImage->hPlugin != NIL_RTLDRMOD)
    1316                 RTLdrClose(pImage->hPlugin);
    1317 
    13181152            if (pImage->pszFilename)
    13191153                RTStrFree(pImage->pszFilename);
     
    14391273        pImage->pVDIfsImage = pVDIfsImage;
    14401274
    1441         rc = vdFindBackend(pszBackend, &pImage->Backend, &pImage->hPlugin);
     1275        rc = vdFindBackend(pszBackend, &pImage->Backend);
    14421276        if (RT_FAILURE(rc))
    14431277            break;
     
    15461380        if (pImage)
    15471381        {
    1548             if (pImage->hPlugin != NIL_RTLDRMOD)
    1549                 RTLdrClose(pImage->hPlugin);
    1550 
    15511382            if (pImage->pszFilename)
    15521383                RTStrFree(pImage->pszFilename);
     
    16411472        }
    16421473
    1643         rc = vdFindBackend(pszBackend, &pImage->Backend, &pImage->hPlugin);
     1474        rc = vdFindBackend(pszBackend, &pImage->Backend);
    16441475        if (RT_FAILURE(rc))
    16451476            break;
     
    17391570    if (RT_FAILURE(rc))
    17401571    {
    1741         if (pImage->hPlugin != NIL_RTLDRMOD)
    1742             RTLdrClose(pImage->hPlugin);
    1743 
    17441572        if (pImage)
    17451573        {
     
    21031931            pImageFrom->pvBackendData = NULL;
    21041932
    2105             if (pImageFrom->hPlugin != NIL_RTLDRMOD)
    2106                 RTLdrClose(pImageFrom->hPlugin);
    2107 
    21081933            if (pImageFrom->pszFilename)
    21091934                RTStrFree(pImageFrom->pszFilename);
     
    22302055
    22312056            /* Free remaining resources. */
    2232             if (pImageFrom->hPlugin != NIL_RTLDRMOD)
    2233                 RTLdrClose(pImageFrom->hPlugin);
    2234 
    22352057            if (pImageFrom->pszFilename)
    22362058                RTStrFree(pImageFrom->pszFilename);
     
    22512073
    22522074        /* Free remaining resources. */
    2253         if (pImageTo->hPlugin != NIL_RTLDRMOD)
    2254             RTLdrClose(pImageTo->hPlugin);
    2255 
    22562075        if (pImageTo->pszFilename)
    22572076            RTStrFree(pImageTo->pszFilename);
     
    23072126        rc = pImage->Backend->pfnClose(pImage->pvBackendData, fDelete);
    23082127        /* Free remaining resources related to the image. */
    2309         if (pImage->hPlugin != NIL_RTLDRMOD)
    2310         {
    2311             RTLdrClose(pImage->hPlugin);
    2312             pImage->hPlugin = NIL_RTLDRMOD;
    2313         }
    23142128        RTStrFree(pImage->pszFilename);
    23152129        RTMemFree(pImage);
     
    24012215                rc = rc2;
    24022216            /* Free remaining resources related to the image. */
    2403             if (pImage->hPlugin != NIL_RTLDRMOD)
    2404             {
    2405                 RTLdrClose(pImage->hPlugin);
    2406                 pImage->hPlugin = NIL_RTLDRMOD;
    2407             }
    24082217            RTStrFree(pImage->pszFilename);
    24092218            RTMemFree(pImage);
  • trunk/src/VBox/Devices/Storage/VBoxHDD-newInternal.h

    r11484 r14852  
    7070     */
    7171    PCVDCONFIGINFO paConfigInfo;
     72
     73    /**
     74     * Handle of loaded plugin library, NIL_RTLDRMOD for static backends.
     75     */
     76    RTLDRMOD hPlugin;
    7277
    7378    /**
  • trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp

    r14270 r14852  
    18691869    /* paConfigInfo */
    18701870    NULL,
     1871    /* hPlugin */
     1872    NIL_RTLDRMOD,
    18711873    /* pfnCheckIfValid */
    18721874    vdiCheckIfValid,
  • trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp

    r14321 r14852  
    18681868    /* paConfigInfo */
    18691869    NULL,
     1870    /* hPlugin */
     1871    NIL_RTLDRMOD,
    18701872    /* pfnCheckIfValid */
    18711873    vhdCheckIfValid,
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r14302 r14852  
    53175317    /* paConfigInfo */
    53185318    NULL,
     5319    /* hPlugin */
     5320    NIL_RTLDRMOD,
    53195321    /* pfnCheckIfValid */
    53205322    vmdkCheckIfValid,
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r14783 r14852  
    489489# error "Port me!"
    490490#endif
     491    /* Unload plugin backends. */
     492    VDShutdown();
    491493
    492494    LogFlowThisFuncLeave();
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