VirtualBox

Changeset 33521 in vbox for trunk


Ignore:
Timestamp:
Oct 27, 2010 3:20:21 PM (14 years ago)
Author:
vboxsync
Message:

ExtPack: More code.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ExtPackManagerImpl.cpp

    r33487 r33521  
    2222#include "ExtPackManagerImpl.h"
    2323
     24#include <iprt/ctype.h>
    2425#include <iprt/dir.h>
     26#include <iprt/env.h>
    2527#include <iprt/file.h>
    2628#include <iprt/ldr.h>
    2729#include <iprt/param.h>
    2830#include <iprt/path.h>
     31#include <iprt/pipe.h>
     32#include <iprt/process.h>
     33#include <iprt/string.h>
    2934
    3035#include <VBox/com/array.h>
     36#include <VBox/com/ErrorInfo.h>
    3137#include <VBox/log.h>
    3238#include "AutoCaller.h"
     39
     40
     41/*******************************************************************************
     42*   Defined Constants And Macros                                               *
     43*******************************************************************************/
     44/** @name VBOX_EXTPACK_HELPER_NAME
     45 * The name of the utility program we employ to install and uninstall the
     46 * extension packs.  This is a set-uid-to-root binary on unixy platforms, which
     47 * is why it has to be a separate program.
     48 */
     49#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     50# define VBOX_EXTPACK_HELPER_NAME   "VBoxExtPackHelper.exe"
     51#else
     52# define VBOX_EXTPACK_HELPER_NAME   "VBoxExtPackHelper"
     53#endif
    3354
    3455
     
    220241}
    221242
     243/**
     244 * Refreshes the extension pack state.
     245 *
     246 * This is called by the manager so that the on disk changes are picked up.
     247 *
     248 * @returns S_OK or COM error status with error information.
     249 * @param   pfCanDelete     Optional can-delete-this-object output indicator.
     250 */
     251HRESULT ExtPack::refresh(bool *pfCanDelete)
     252{
     253    if (pfCanDelete)
     254        *pfCanDelete = false;
     255    return S_OK;
     256}
     257
    222258
    223259
     
    358394        AutoReadLock autoLock(this COMMA_LOCKVAL_SRC_POS);
    359395
    360         hrc = VBOX_E_OBJECT_NOT_FOUND;
    361         for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
    362              it != m->llInstalledExtPacks.end();
    363              it++)
    364         {
    365             ExtPack::Data *pExtPackData = (*it)->m;
    366             if (   pExtPackData
    367                 && pExtPackData->strName.compare(strName) == 0)
    368             {
    369                 (*it).queryInterfaceTo(a_pExtPack);
    370                 hrc = S_OK;
    371                 break;
    372             }
    373         }
     396        ComPtr<ExtPack> ptrExtPack = findExtPack(strName.c_str());
     397        if (!ptrExtPack.isNull())
     398            ptrExtPack.queryInterfaceTo(a_pExtPack);
     399        else
     400            hrc = VBOX_E_OBJECT_NOT_FOUND;
    374401    }
    375402
     
    383410    Utf8Str strTarball(a_bstrTarball);
    384411
     412    AutoCaller autoCaller(this);
     413    HRESULT hrc = autoCaller.rc();
     414    if (SUCCEEDED(hrc))
     415    {
     416        AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
     417
     418        /*
     419         * Check that the file exists and that we can access it.
     420         */
     421        if (RTFileExists(strTarball.c_str()))
     422        {
     423            RTFILE hFile;
     424            int vrc = RTFileOpen(&hFile, strTarball.c_str(), RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN);
     425            if (RT_SUCCESS(vrc))
     426            {
     427                RTFSOBJINFO ObjInfo;
     428                vrc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
     429                if (   RT_SUCCESS(vrc)
     430                    && RTFS_IS_FILE(ObjInfo.Attr.fMode))
     431                {
     432                    /*
     433                     * Derive the name of the extension pack from the file
     434                     * name.
     435                     *
     436                     * RESTRICTION: The name can only contain english alphabet
     437                     *              charactes, decimal digits and space.
     438                     *              Impose a max length of 64 chars.
     439                     */
     440                    char *pszName = RTStrDup(RTPathFilename(strTarball.c_str()));
     441                    if (pszName)
     442                    {
     443                        char *pszEnd = pszName;
     444                        while (RT_C_IS_ALNUM(*pszEnd) || *pszEnd == ' ')
     445                            pszEnd++;
     446                        if (   pszEnd == pszName
     447                            || pszEnd - pszName <= 64)
     448                        {
     449                            *pszEnd = '\0';
     450
     451                            /*
     452                             * Refresh the data we have on the extension pack
     453                             * as it may be made stale by direct meddling or
     454                             * some other user.
     455                             */
     456                            ExtPack *pExtPack;
     457                            hrc = refreshExtPack(pszName, false /*a_fUnsuableIsError*/, &pExtPack);
     458                            if (SUCCEEDED(hrc) && !pExtPack)
     459                            {
     460                                /*
     461                                 * Run the set-uid-to-root binary that performs the actual
     462                                 * installation.  Then create an object for the packet (we
     463                                 * do this even on failure, to be on the safe side).
     464                                 */
     465                                char szTarballFd[64];
     466                                RTStrPrintf(szTarballFd, sizeof(szTarballFd), "0x%RX64",
     467                                            (uint64_t)RTFileToNative(hFile));
     468
     469                                hrc = runSetUidToRootHelper("install",
     470                                                            "--basepath",   m->strBasePath.c_str(),
     471                                                            "--name",       pszName,
     472                                                            "--tarball",    strTarball.c_str(),
     473                                                            "--tarball-fd", &szTarballFd[0],
     474                                                            NULL);
     475                                if (SUCCEEDED(hrc))
     476                                {
     477                                    hrc = refreshExtPack(pszName, true /*a_fUnsuableIsError*/, &pExtPack);
     478                                    if (SUCCEEDED(hrc))
     479                                        LogRel(("ExtPackManager: Successfully installed extension pack '%s'.\n", pszName));
     480                                }
     481                                else
     482                                {
     483                                    ErrorInfoKeeper Eik;
     484                                    refreshExtPack(pszName, false /*a_fUnsuableIsError*/, NULL);
     485                                }
     486                            }
     487                            else if (SUCCEEDED(hrc))
     488                                hrc = setError(E_FAIL,
     489                                               tr("Extension pack '%s' is already installed."
     490                                                  " In case of a reinstallation, please uninstall it first"),
     491                                               pszName);
     492                        }
     493                        else
     494                            hrc = setError(E_FAIL, tr("Malformed '%s' file name"), strTarball.c_str());
     495                    }
     496                    else
     497                        hrc = E_OUTOFMEMORY;
     498                }
     499                else if (RT_SUCCESS(vrc))
     500                    hrc = setError(E_FAIL, tr("'%s' is not a regular file"), strTarball.c_str());
     501                else
     502                    hrc = setError(E_FAIL, tr("Failed to query info on '%s' (%Rrc)"), strTarball.c_str(), vrc);
     503                RTFileClose(hFile);
     504            }
     505            else
     506                hrc = setError(E_FAIL, tr("Failed to open '%s' (%Rrc)"), strTarball.c_str(), vrc);
     507        }
     508        else if (RTPathExists(strTarball.c_str()))
     509            hrc = setError(E_FAIL, tr("'%s' is not a regular file"), strTarball.c_str());
     510        else
     511            hrc = setError(E_FAIL, tr("File '%s' was inaccessible or not found"), strTarball.c_str());
     512    }
     513
     514    return hrc;
     515}
     516
     517STDMETHODIMP ExtPackManager::Uninstall(IN_BSTR a_bstrName, BOOL a_fForcedRemoval)
     518{
     519    CheckComArgNotNull(a_bstrName);
     520    Utf8Str strName(a_bstrName);
     521
     522    AutoCaller autoCaller(this);
     523    HRESULT hrc = autoCaller.rc();
     524    if (SUCCEEDED(hrc))
     525    {
     526        AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
     527
     528        /*
     529         * Refresh the data we have on the extension pack as it may be made
     530         * stale by direct meddling or some other user.
     531         */
     532        ExtPack *pExtPack;
     533        hrc = refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
     534        if (SUCCEEDED(hrc))
     535        {
     536            if (!pExtPack)
     537            {
     538                LogRel(("ExtPackManager: Extension pack '%s' is not installed, so nothing to uninstall.\n", strName.c_str()));
     539                hrc = S_OK;             /* nothing to uninstall */
     540            }
     541            else
     542            {
     543                /*
     544                 * Run the set-uid-to-root binary that performs the
     545                 * uninstallation.  Then refresh the object.
     546                 *
     547                 * This refresh is theorically subject to races, but it's of
     548                 * the don't-do-that variety.
     549                 */
     550                hrc = runSetUidToRootHelper("uninstall",
     551                                            "--basepath", m->strBasePath.c_str(),
     552                                            "--name",     strName.c_str(),
     553                                            NULL);
     554                if (SUCCEEDED(hrc))
     555                {
     556                    hrc = refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, &pExtPack);
     557                    if (SUCCEEDED(hrc))
     558                    {
     559                        if (!pExtPack)
     560                            LogRel(("ExtPackManager: Successfully uninstalled extension pack '%s'.\n", strName.c_str()));
     561                        else
     562                            hrc = setError(E_UNEXPECTED,
     563                                           tr("Uninstall extension pack '%s' failed under mysterious circumstances"),
     564                                           strName.c_str());
     565                    }
     566                }
     567                else
     568                {
     569                    ErrorInfoKeeper Eik;
     570                    refreshExtPack(strName.c_str(), false /*a_fUnsuableIsError*/, NULL);
     571                }
     572
     573            }
     574        }
     575    }
     576
     577    return hrc;
     578}
     579
     580
     581/**
     582 * Runs the helper program that does the privileged operations.
     583 *
     584 * @returns S_OK or a failure status with error information set.
     585 * @param   a_pszCommand        The command to execute.
     586 * @param   ...                 The argument strings that goes along with the
     587 *                              command. Maximum is about 16.  Terminated by a
     588 *                              NULL.
     589 */
     590HRESULT ExtPackManager::runSetUidToRootHelper(const char *a_pszCommand, ...)
     591{
    385592    /*
    386      * Check that the file exists and that we can access it.
     593     * Calculate the path to the helper program.
     594     */
     595    char szExecName[RTPATH_MAX];
     596    int vrc = RTPathAppPrivateArch(szExecName, sizeof(szExecName));
     597    AssertLogRelRCReturn(vrc, E_UNEXPECTED);
     598
     599    vrc = RTPathAppend(szExecName, sizeof(szExecName), VBOX_EXTPACK_HELPER_NAME);
     600    AssertLogRelRCReturn(vrc, E_UNEXPECTED);
     601
     602    /*
     603     * Convert the variable argument list to a RTProcCreate argument vector.
     604     */
     605    const char *apszArgs[20];
     606    unsigned    cArgs = 0;
     607    apszArgs[cArgs++] = &szExecName[0];
     608    apszArgs[cArgs++] = a_pszCommand;
     609
     610    va_list va;
     611    va_start(va, a_pszCommand);
     612    const char *pszLastArg;
     613    LogRel(("ExtPack: Executing '%s'", szExecName));
     614    do
     615    {
     616        LogRel((" '%s'", apszArgs[cArgs - 1]));
     617        AssertReturn(cArgs < RT_ELEMENTS(apszArgs) - 1, E_UNEXPECTED);
     618        pszLastArg = va_arg(va, const char *);
     619        apszArgs[cArgs++] = pszLastArg;
     620    } while (pszLastArg != NULL);
     621    LogRel(("\n"));
     622    va_end(va);
     623    apszArgs[cArgs] = NULL;
     624
     625    /*
     626     * Create a PIPE which we attach to stderr so that we can read the error
     627     * message on failure and report it back to the caller.
     628     */
     629    RTPIPE      hPipeR;
     630    RTHANDLE    hStdErrPipe;
     631    hStdErrPipe.enmType = RTHANDLETYPE_PIPE;
     632    vrc = RTPipeCreate(&hPipeR, &hStdErrPipe.u.hPipe, RTPIPE_C_INHERIT_WRITE);
     633    AssertLogRelRCReturn(vrc, E_UNEXPECTED);
     634
     635    /*
     636     * Spawn the process.
    387637     */
    388638    HRESULT hrc;
    389     if (RTFileExists(strTarball.c_str()))
    390     {
    391         RTFILE hFile;
    392         int vrc = RTFileOpen(&hFile, strTarball.c_str(), RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN);
    393         if (RT_SUCCESS(vrc))
     639    RTPROCESS hProcess;
     640    vrc = RTProcCreateEx(szExecName,
     641                         apszArgs,
     642                         RTENV_DEFAULT,
     643                         0 /*fFlags*/,
     644                         NULL /*phStdIn*/,
     645                         NULL /*phStdOut*/,
     646                         &hStdErrPipe,
     647                         NULL /*pszAsUser*/,
     648                         NULL /*pszPassword*/,
     649                         &hProcess);
     650    if (RT_SUCCESS(vrc))
     651    {
     652        vrc = RTPipeClose(hStdErrPipe.u.hPipe);
     653        hStdErrPipe.u.hPipe = NIL_RTPIPE;
     654
     655        /*
     656         * Read the pipe output until the process completes.
     657         */
     658        RTPROCSTATUS    ProcStatus   = { -42, RTPROCEXITREASON_ABEND };
     659        size_t          cbStdErrBuf  = 0;
     660        size_t          offStdErrBuf = 0;
     661        char           *pszStdErrBuf = NULL;
     662        do
    394663        {
    395664            /*
    396              * .
     665             * Service the pipe. Block waiting for output or the pipe breaking
     666             * when the process terminates.
    397667             */
    398 
    399 
    400             RTFileClose(hFile);
     668            if (hPipeR != NIL_RTPIPE)
     669            {
     670                char    achBuf[16]; //1024
     671                size_t  cbRead;
     672                vrc = RTPipeReadBlocking(hPipeR, achBuf, sizeof(achBuf), &cbRead);
     673                if (RT_SUCCESS(vrc))
     674                {
     675                    /* grow the buffer? */
     676                    size_t cbBufReq = offStdErrBuf + cbRead + 1;
     677                    if (   cbBufReq > cbStdErrBuf
     678                        && cbBufReq < _256K)
     679                    {
     680                        size_t cbNew = RT_ALIGN_Z(cbBufReq, 16); // 1024
     681                        void  *pvNew = RTMemRealloc(pszStdErrBuf, cbNew);
     682                        if (pvNew)
     683                        {
     684                            pszStdErrBuf = (char *)pvNew;
     685                            cbStdErrBuf  = cbNew;
     686                        }
     687                    }
     688
     689                    /* append if we've got room. */
     690                    if (cbBufReq <= cbStdErrBuf)
     691                    {
     692                        memcpy(&pszStdErrBuf[offStdErrBuf], achBuf, cbRead);
     693                        offStdErrBuf = offStdErrBuf + cbRead;
     694                        pszStdErrBuf[offStdErrBuf] = '\0';
     695                    }
     696                }
     697                else
     698                {
     699                    AssertLogRelMsg(vrc == VERR_BROKEN_PIPE, ("%Rrc\n", vrc));
     700                    RTPipeClose(hPipeR);
     701                    hPipeR = NIL_RTPIPE;
     702                }
     703            }
     704
     705            /*
     706             * Service the process.  Block if we have no pipe.
     707             */
     708            if (hProcess != NIL_RTPROCESS)
     709            {
     710                vrc = RTProcWait(hProcess,
     711                                 hPipeR == NIL_RTPIPE ? RTPROCWAIT_FLAGS_BLOCK : RTPROCWAIT_FLAGS_NOBLOCK,
     712                                 &ProcStatus);
     713                if (RT_SUCCESS(vrc))
     714                    hProcess = NIL_RTPROCESS;
     715                else
     716                    AssertLogRelMsgStmt(vrc != VERR_PROCESS_RUNNING, ("%Rrc\n", vrc), hProcess = NIL_RTPROCESS);
     717            }
     718        } while (   hPipeR != NIL_RTPIPE
     719                 || hProcess != NIL_RTPROCESS);
     720
     721        /*
     722         * Compose the status code and, on failure, error message.
     723         */
     724        LogRel(("ExtPack: enmReason=%d iStatus=%d stderr='%s'\n",
     725                ProcStatus.enmReason, ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : ""));
     726
     727        if (   ProcStatus.enmReason == RTPROCEXITREASON_NORMAL
     728            && ProcStatus.iStatus   == 0
     729            && offStdErrBuf         == 0)
     730            hrc = S_OK;
     731        else if (ProcStatus.enmReason == RTPROCEXITREASON_NORMAL)
     732        {
     733            AssertMsg(ProcStatus.iStatus != 0, ("%s\n", pszStdErrBuf));
     734            hrc = setError(E_UNEXPECTED, tr("The installer failed with exit code %d: %s"),
     735                           ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
     736        }
     737        else if (ProcStatus.enmReason == RTPROCEXITREASON_SIGNAL)
     738            hrc = setError(E_UNEXPECTED, tr("The installer was killed by signal #d (stderr: %s)"),
     739                           ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
     740        else if (ProcStatus.enmReason == RTPROCEXITREASON_ABEND)
     741            hrc = setError(E_UNEXPECTED, tr("The installer aborted abnormally (stderr: %s)"),
     742                           offStdErrBuf ? pszStdErrBuf : "");
     743        else
     744            hrc = setError(E_UNEXPECTED, tr("internal error: enmReason=%d iStatus=%d stderr='%s'"),
     745                           ProcStatus.enmReason, ProcStatus.iStatus, offStdErrBuf ? pszStdErrBuf : "");
     746
     747        RTMemFree(pszStdErrBuf);
     748    }
     749    else
     750        hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to launch the helper application '%s' (%Rrc)"), szExecName, vrc);
     751
     752    RTPipeClose(hPipeR);
     753    RTPipeClose(hStdErrPipe.u.hPipe);
     754
     755    return hrc;
     756}
     757
     758/**
     759 * Finds an installed extension pack.
     760 *
     761 * @returns Pointer to the extension pack if found, NULL if not. (No reference
     762 *          counting problem here since the caller must be holding the lock.)
     763 * @param   a_pszName       The name of the extension pack.
     764 */
     765ExtPack *ExtPackManager::findExtPack(const char *a_pszName)
     766{
     767    size_t cchName = strlen(a_pszName);
     768
     769    for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
     770         it != m->llInstalledExtPacks.end();
     771         it++)
     772    {
     773        ExtPack::Data *pExtPackData = (*it)->m;
     774        if (   pExtPackData
     775            && pExtPackData->strName.length() == cchName
     776            && pExtPackData->strName.compare(a_pszName, iprt::MiniString::CaseInsensitive) == 0)
     777            return (*it);
     778    }
     779    return NULL;
     780}
     781
     782/**
     783 * Removes an installed extension pack from the internal list.
     784 *
     785 * The package is expected to exist!
     786 *
     787 * @param   a_pszName       The name of the extension pack.
     788 */
     789void ExtPackManager::removeExtPack(const char *a_pszName)
     790{
     791    size_t cchName = strlen(a_pszName);
     792
     793    for (ExtPackList::iterator it = m->llInstalledExtPacks.begin();
     794         it != m->llInstalledExtPacks.end();
     795         it++)
     796    {
     797        ExtPack::Data *pExtPackData = (*it)->m;
     798        if (   pExtPackData
     799            && pExtPackData->strName.length() == cchName
     800            && pExtPackData->strName.compare(a_pszName, iprt::MiniString::CaseInsensitive) == 0)
     801        {
     802            m->llInstalledExtPacks.erase(it);
     803            return;
     804        }
     805    }
     806    AssertMsgFailed(("%s\n", a_pszName));
     807}
     808
     809/**
     810 * Refreshes the specified extension pack.
     811 *
     812 * This may remove the extension pack from the list, so any non-smart pointers
     813 * to the extension pack object may become invalid.
     814 *
     815 * @returns S_OK and *ppExtPack on success, COM status code and error message
     816 *          on failure.
     817 * @param   a_pszName           The extension to update..
     818 * @param   a_fUnsuableIsError  If @c true, report an unusable extension pack
     819 *                              as an error.
     820 * @param   a_ppExtPack         Where to store the pointer to the extension
     821 *                              pack of it is still around after the refresh.
     822 *                              This is optional.
     823 */
     824HRESULT ExtPackManager::refreshExtPack(const char *a_pszName, bool a_fUnsuableIsError, ExtPack **a_ppExtPack)
     825{
     826    HRESULT hrc;
     827    ExtPack *pExtPack = findExtPack(a_pszName);
     828    if (pExtPack)
     829    {
     830        /*
     831         * Refresh existing object.
     832         */
     833        bool fCanDelete;
     834        hrc = pExtPack->refresh(&fCanDelete);
     835        if (SUCCEEDED(hrc))
     836        {
     837            if (fCanDelete)
     838            {
     839                removeExtPack(a_pszName);
     840                pExtPack = NULL;
     841            }
     842        }
     843    }
     844    else
     845    {
     846        /*
     847         * Does the dir exist?  Make some special effort to deal with case
     848         * sensitivie file systems (a_pszName is case insensitive).
     849         */
     850        char szDir[RTPATH_MAX];
     851        int vrc = RTPathJoin(szDir, sizeof(szDir), m->strBasePath.c_str(), a_pszName);
     852        AssertLogRelRCReturn(vrc, E_FAIL);
     853
     854        RTDIRENTRYEX    Entry;
     855        RTFSOBJINFO     ObjInfo;
     856        vrc = RTPathQueryInfoEx(szDir, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     857        bool fExists = RT_SUCCESS(vrc) && RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode);
     858        if (!fExists)
     859        {
     860            PRTDIR pDir;
     861            vrc = RTDirOpen(&pDir, m->strBasePath.c_str());
     862            if (RT_SUCCESS(vrc))
     863            {
     864                for (;;)
     865                {
     866                    vrc = RTDirReadEx(pDir, &Entry, NULL /*pcbDirEntry*/, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     867                    if (RT_FAILURE(vrc))
     868                    {
     869                        AssertLogRelMsg(vrc == VERR_NO_MORE_FILES, ("%Rrc\n", vrc));
     870                        break;
     871                    }
     872                    if (   RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)
     873                        && !RTStrICmp(Entry.szName, a_pszName))
     874                    {
     875                        /*
     876                         * The installed extension pack has a uses different case.
     877                         * Update the name and directory variables.
     878                         */
     879                        vrc = RTPathJoin(szDir, sizeof(szDir), m->strBasePath.c_str(), Entry.szName); /* not really necessary */
     880                        AssertLogRelRCReturnStmt(vrc, E_UNEXPECTED, RTDirClose(pDir));
     881                        a_pszName = Entry.szName;
     882                        fExists   = true;
     883                        break;
     884                    }
     885                }
     886                RTDirClose(pDir);
     887            }
     888        }
     889        if (fExists)
     890        {
     891            /*
     892             * We've got something, create a new extension pack object for it.
     893             */
     894            ComObjPtr<ExtPack> NewExtPack;
     895            hrc = NewExtPack.createObject();
     896            if (SUCCEEDED(hrc))
     897                hrc = NewExtPack->init(a_pszName, m->strBasePath.c_str());
     898            if (SUCCEEDED(hrc))
     899            {
     900                m->llInstalledExtPacks.push_back(NewExtPack);
     901                if (NewExtPack->m->fUsable)
     902                    LogRel(("ExtPackManager: Found extension pack '%s'.\n", a_pszName));
     903                else
     904                    LogRel(("ExtPackManager: Found bad extension pack '%s': %s\n",
     905                            a_pszName, NewExtPack->m->strWhyUnusable.c_str() ));
     906                pExtPack = NewExtPack;
     907            }
    401908        }
    402909        else
    403             hrc = setError(E_FAIL, tr("Failed to open '%s' (%Rrc)"), strTarball.c_str(), vrc);
    404     }
    405     else if (RTPathExists(strTarball.c_str()))
    406         hrc = setError(E_FAIL, tr("'%s' is not a regular file"), strTarball.c_str());
    407     else
    408         hrc = setError(E_FAIL, tr("File '%s' was inaccessible or not found"), strTarball.c_str());
    409     return hrc;
    410 }
    411 
    412 STDMETHODIMP ExtPackManager::Uninstall(IN_BSTR a_bstrName, BOOL a_fForcedRemoval)
    413 {
    414     NOREF(a_bstrName); NOREF(a_fForcedRemoval);
    415     return E_NOTIMPL;
     910            hrc = S_OK;
     911    }
     912
     913    /*
     914     * Report error if not usable, if that is desired.
     915     */
     916    if (   SUCCEEDED(hrc)
     917        && pExtPack
     918        && a_fUnsuableIsError
     919        && !pExtPack->m->fUsable)
     920        hrc = setError(E_FAIL, "%s", pExtPack->m->strWhyUnusable.c_str());
     921
     922    if (a_ppExtPack)
     923        *a_ppExtPack = pExtPack;
     924    return hrc;
    416925}
    417926
     
    430939}
    431940
     941
    432942/* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/include/ExtPackManagerImpl.h

    r33474 r33521  
    6363     * @{ */
    6464    void *getCallbackTable();
     65    HRESULT refresh(bool *pfCanDelete);
    6566    /** @}  */
    6667
     
    109110    /** @name Internal interfaces used by other Main classes.
    110111     * @{ */
    111     int callAllConfigHooks(IConsole *a_pConsole, PVM a_pVM);
    112     int callAllNewMachineHooks(IMachine *a_pMachine);
     112    int         callAllConfigHooks(IConsole *a_pConsole, PVM a_pVM);
     113    int         callAllNewMachineHooks(IMachine *a_pMachine);
    113114    /** @}  */
     115
     116private:
     117    HRESULT     runSetUidToRootHelper(const char *a_pszCommand, ...);
     118    ExtPack    *findExtPack(const char *a_pszName);
     119    void        removeExtPack(const char *a_pszName);
     120    HRESULT     refreshExtPack(const char *a_pszName, bool a_fUnsuableIsError, ExtPack **a_ppExtPack);
    114121
    115122private:
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