VirtualBox

Changeset 35523 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jan 13, 2011 1:12:03 PM (14 years ago)
Author:
vboxsync
Message:

Main,VBoxManage: Implemented the progress objects for ExtPackManager::Uninstall and ExtPackFile::Install. Fixed a bug in ExtPackFile wrt cleaning up on failure.

Location:
trunk/src/VBox
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp

    r35517 r35523  
    859859        ComPtr<IProgress> ptrProgress;
    860860        CHECK_ERROR2_RET(ptrExtPackFile, Install(fReplace, NULL, ptrProgress.asOutParam()), RTEXITCODE_FAILURE);
    861         if (!ptrProgress.isNull())
    862             CHECK_ERROR2_RET(ptrProgress, WaitForCompletion(-1), RTEXITCODE_FAILURE);
     861        hrc = showProgress(ptrProgress);
     862        if (FAILED(hrc))
     863        {
     864            com::ProgressErrorInfo ErrInfo(ptrProgress);
     865            if (ErrInfo.isBasicAvailable())
     866                RTMsgError("Failed to install \"%s\": %lS", szPath, ErrInfo.getText().raw());
     867            else
     868                RTMsgError("Failed to install \"%s\": No error message available!", szPath);
     869            return RTEXITCODE_FAILURE;
     870        }
    863871        RTPrintf("Successfully installed \"%lS\".\n", bstrName.raw());
    864872    }
     
    898906        ComPtr<IProgress> ptrProgress;
    899907        CHECK_ERROR2_RET(ptrExtPackMgr, Uninstall(bstrName.raw(), fForced, NULL, ptrProgress.asOutParam()), RTEXITCODE_FAILURE);
    900         if (!ptrProgress.isNull())
    901             CHECK_ERROR2_RET(ptrProgress, WaitForCompletion(-1), RTEXITCODE_FAILURE);
     908        hrc = showProgress(ptrProgress);
     909        if (FAILED(hrc))
     910        {
     911            com::ProgressErrorInfo ErrInfo(ptrProgress);
     912            if (ErrInfo.isBasicAvailable())
     913                RTMsgError("Failed to uninstall \"%s\": %lS", pszName, ErrInfo.getText().raw());
     914            else
     915                RTMsgError("Failed to uninstall \"%s\": No error message available!", pszName);
     916            return RTEXITCODE_FAILURE;
     917        }
    902918        RTPrintf("Successfully uninstalled \"%s\".\n", pszName);
    903919    }
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r35460 r35523  
    1484914849      <param name="progess" type="IProgress" dir="return">
    1485014850        <desc>
    14851           Progress object for the operation if it was decided that it should
    14852           be executed asynchronously - i.e. never in 4.0.0, but maybe in 4.0.x.
     14851          Progress object for the operation.
    1485314852        </desc>
    1485414853      </param>
     
    1492114920      <param name="progess" type="IProgress" dir="return">
    1492214921        <desc>
    14923           Progress object for the operation if it was decided that it should
    14924           be executed asynchronously - i.e. never in 4.0.0, but maybe in 4.0.x.
     14922          Progress object for the operation.
    1492514923        </desc>
    1492614924      </param>
  • trunk/src/VBox/Main/include/ExtPackManagerImpl.h

    r35273 r35523  
    4646    HRESULT     FinalConstruct();
    4747    void        FinalRelease();
    48     HRESULT     initWithFile(const char *a_pszFile, class ExtPackManager *a_pExtPackMgr);
     48    HRESULT     initWithFile(const char *a_pszFile, class ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox);
    4949    void        uninit();
    5050    RTMEMEF_NEW_AND_DELETE_OPERATORS();
     
    219219    /** @name Internal interfaces used by other Main classes.
    220220     * @{ */
    221     HRESULT     doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace, Utf8Str const *a_pstrDisplayInfo,
    222                           IProgress **a_ppProgress);
     221    static DECLCALLBACK(int) doInstallThreadProc(RTTHREAD hThread, void *pvJob);
     222    HRESULT     doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace, Utf8Str const *a_pstrDisplayInfo);
     223    static DECLCALLBACK(int) doUninstallThreadProc(RTTHREAD hThread, void *pvJob);
     224    HRESULT     doUninstall(const Utf8Str *a_pstrName, bool a_fForcedRemoval, const Utf8Str *a_pstrDisplayInfo);
    223225    void        callAllVirtualBoxReadyHooks(void);
    224226    void        callAllConsoleReadyHooks(IConsole *a_pConsole);
  • trunk/src/VBox/Main/include/ExtPackUtil.h

    r34938 r35523  
    110110
    111111
     112void                VBoxExtPackInitDesc(PVBOXEXTPACKDESC a_pExtPackDesc);
    112113iprt::MiniString   *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
    113114iprt::MiniString   *VBoxExtPackLoadDescFromVfsFile(RTVFSFILE hVfsFile, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo);
  • trunk/src/VBox/Main/src-all/ExtPackManagerImpl.cpp

    r35413 r35523  
    4444#include "AutoCaller.h"
    4545#include "Global.h"
     46#include "ProgressImpl.h"
    4647#include "SystemPropertiesImpl.h"
    4748#include "VirtualBoxImpl.h"
     
    9495    /** Pointer to the extension pack manager. */
    9596    ComObjPtr<ExtPackManager> ptrExtPackMgr;
     97    /** Pointer to the VirtualBox object so we can create a progress object. */
     98    VirtualBox         *pVirtualBox;
    9699
    97100    RTMEMEF_NEW_AND_DELETE_OPERATORS();
     
    158161};
    159162
     163/**
     164 * Extension pack installation job.
     165 */
     166typedef struct EXTPACKINSTALLJOB
     167{
     168    /** Smart pointer to the extension pack file. */
     169    ComPtr<ExtPackFile>     ptrExtPackFile;
     170    /** The replace argument. */
     171    bool                    fReplace;
     172    /** The display info argument.  */
     173    Utf8Str                 strDisplayInfo;
     174    /** Smart pointer to the extension manager. */
     175    ComPtr<ExtPackManager>  ptrExtPackMgr;
     176    /** Smart pointer to the progress object for this job. */
     177    ComObjPtr<Progress>     ptrProgress;
     178} EXTPACKINSTALLJOB;
     179/** Pointer to an extension pack installation job. */
     180typedef EXTPACKINSTALLJOB *PEXTPACKINSTALLJOB;
     181
     182/**
     183 * Extension pack uninstallation job.
     184 */
     185typedef struct EXTPACKUNINSTALLJOB
     186{
     187    /** Smart pointer to the extension manager. */
     188    ComPtr<ExtPackManager>  ptrExtPackMgr;
     189    /** The name of the extension pack. */
     190    Utf8Str                 strName;
     191    /** The replace argument. */
     192    bool                    fForcedRemoval;
     193    /** The display info argument.  */
     194    Utf8Str                 strDisplayInfo;
     195    /** Smart pointer to the progress object for this job. */
     196    ComObjPtr<Progress>     ptrProgress;
     197} EXTPACKUNINSTALLJOB;
     198/** Pointer to an extension pack uninstallation job. */
     199typedef EXTPACKUNINSTALLJOB *PEXTPACKUNINSTALLJOB;
     200
    160201
    161202DEFINE_EMPTY_CTOR_DTOR(ExtPackFile)
     
    180221 * @param   a_pszFile       The path to the extension pack file.
    181222 * @param   a_pExtPackMgr   Pointer to the extension pack manager.
    182  */
    183 HRESULT ExtPackFile::initWithFile(const char *a_pszFile, ExtPackManager *a_pExtPackMgr)
     223 * @param   a_pVirtualBox   Pointer to the VirtualBox object.
     224 */
     225HRESULT ExtPackFile::initWithFile(const char *a_pszFile, ExtPackManager *a_pExtPackMgr, VirtualBox *a_pVirtualBox)
    184226{
    185227    AutoInitSpan autoInitSpan(this);
     
    190232     */
    191233    m = new ExtPackFile::Data;
    192     m->Desc.strName                 = NULL;
     234    VBoxExtPackInitDesc(&m->Desc);
    193235    RT_ZERO(m->ObjInfoDesc);
    194236    m->fUsable                      = false;
     
    198240    m->hOurManifest                 = NIL_RTMANIFEST;
    199241    m->ptrExtPackMgr                = a_pExtPackMgr;
     242    m->pVirtualBox                  = a_pVirtualBox;
    200243
    201244    iprt::MiniString *pstrTarName = VBoxExtPackExtractNameFromTarballPath(a_pszFile);
     
    589632    if (a_ppProgress)
    590633        *a_ppProgress = NULL;
    591     Utf8Str strDisplayInfo(a_bstrDisplayInfo);
    592634
    593635    AutoCaller autoCaller(this);
     
    596638    {
    597639        if (m->fUsable)
    598             hrc = m->ptrExtPackMgr->doInstall(this, RT_BOOL(a_fReplace), &strDisplayInfo, a_ppProgress);
     640        {
     641            PEXTPACKINSTALLJOB pJob = NULL;
     642            try
     643            {
     644                pJob = new EXTPACKINSTALLJOB;
     645                pJob->ptrExtPackFile    = this;
     646                pJob->fReplace          = a_fReplace;
     647                pJob->strDisplayInfo    = a_bstrDisplayInfo;
     648                pJob->ptrExtPackMgr     = m->ptrExtPackMgr;
     649                hrc = pJob->ptrProgress.createObject();
     650                if (SUCCEEDED(hrc))
     651                {
     652                    Bstr bstrDescription = tr("Installing extension pack");
     653                    hrc = pJob->ptrProgress->init(
     654#ifndef VBOX_COM_INPROC
     655                                                  m->pVirtualBox,
     656#endif
     657                                                  static_cast<IExtPackFile *>(this),
     658                                                  bstrDescription.raw(),
     659                                                  FALSE /*aCancelable*/,
     660                                                  NULL /*aId*/);
     661                }
     662                if (SUCCEEDED(hrc))
     663                {
     664                    ComPtr<Progress> ptrProgress = pJob->ptrProgress;
     665                    int vrc = RTThreadCreate(NULL /*phThread*/, ExtPackManager::doInstallThreadProc, pJob, 0,
     666                                             RTTHREADTYPE_DEFAULT, 0 /*fFlags*/, "ExtPackInst");
     667                    if (RT_SUCCESS(vrc))
     668                    {
     669                        pJob = NULL; /* the thread deletes it */
     670                        ptrProgress.queryInterfaceTo(a_ppProgress);
     671                    }
     672                    else
     673                        hrc = setError(VBOX_E_IPRT_ERROR, tr("RTThreadCreate failed with %Rrc"), vrc);
     674                }
     675            }
     676            catch (std::bad_alloc)
     677            {
     678                hrc = E_OUTOFMEMORY;
     679            }
     680            if (pJob)
     681                delete pJob;
     682        }
    599683        else
    600684            hrc = setError(E_FAIL, "%s", m->strWhyUnusable.c_str());
     
    663747     */
    664748    m = new Data;
     749    VBoxExtPackInitDesc(&m->Desc);
    665750    m->Desc.strName                 = a_pszName;
    666751    RT_ZERO(m->ObjInfoDesc);
     
    19212006    HRESULT hrc = NewExtPackFile.createObject();
    19222007    if (SUCCEEDED(hrc))
    1923         hrc = NewExtPackFile->initWithFile(strTarball.c_str(), this);
     2008        hrc = NewExtPackFile->initWithFile(strTarball.c_str(), this, m->pVirtualBox);
    19242009    if (SUCCEEDED(hrc))
    19252010        NewExtPackFile.queryInterfaceTo(a_ppExtPackFile);
     
    19322017{
    19332018    CheckComArgNotNull(a_bstrName);
    1934     Utf8Str strName(a_bstrName);
    1935     Utf8Str strDisplayInfo(a_bstrDisplayInfo);
    19362019    if (a_ppProgress)
    19372020        *a_ppProgress = NULL;
     
    19422025    if (SUCCEEDED(hrc))
    19432026    {
    1944         AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
    1945 
    1946         /*
    1947          * Refresh the data we have on the extension pack as it may be made
    1948          * stale by direct meddling or some other user.
    1949          */
    1950         ExtPack *pExtPack;
    1951         hrc = refreshExtPack(strName.c_str(), false /*a_fUnusableIsError*/, &pExtPack);
    1952         if (SUCCEEDED(hrc))
    1953         {
    1954             if (!pExtPack)
     2027        PEXTPACKUNINSTALLJOB pJob = NULL;
     2028        try
     2029        {
     2030            pJob = new EXTPACKUNINSTALLJOB;
     2031            pJob->ptrExtPackMgr     = this;
     2032            pJob->strName           = a_bstrName;
     2033            pJob->fForcedRemoval    = a_fForcedRemoval != FALSE;
     2034            pJob->strDisplayInfo    = a_bstrDisplayInfo;
     2035            hrc = pJob->ptrProgress.createObject();
     2036            if (SUCCEEDED(hrc))
    19552037            {
    1956                 LogRel(("ExtPackManager: Extension pack '%s' is not installed, so nothing to uninstall.\n", strName.c_str()));
    1957                 hrc = S_OK;             /* nothing to uninstall */
     2038                Bstr bstrDescription = tr("Uninstalling extension pack");
     2039                hrc = pJob->ptrProgress->init(
     2040#ifndef VBOX_COM_INPROC
     2041                                              m->pVirtualBox,
     2042#endif
     2043                                              static_cast<IExtPackManager *>(this),
     2044                                              bstrDescription.raw(),
     2045                                              FALSE /*aCancelable*/,
     2046                                              NULL /*aId*/);
    19582047            }
    1959             else
     2048            if (SUCCEEDED(hrc))
    19602049            {
    1961                 /*
    1962                  * Call the uninstall hook and unload the main dll.
    1963                  */
    1964                 hrc = pExtPack->callUninstallHookAndClose(m->pVirtualBox, a_fForcedRemoval != FALSE);
    1965                 if (SUCCEEDED(hrc))
     2050                ComPtr<Progress> ptrProgress = pJob->ptrProgress;
     2051                int vrc = RTThreadCreate(NULL /*phThread*/, ExtPackManager::doUninstallThreadProc, pJob, 0,
     2052                                         RTTHREADTYPE_DEFAULT, 0 /*fFlags*/, "ExtPackUninst");
     2053                if (RT_SUCCESS(vrc))
    19662054                {
    1967                     /*
    1968                      * Run the set-uid-to-root binary that performs the
    1969                      * uninstallation.  Then refresh the object.
    1970                      *
    1971                      * This refresh is theorically subject to races, but it's of
    1972                      * the don't-do-that variety.
    1973                      */
    1974                     const char *pszForcedOpt = a_fForcedRemoval ? "--forced" : NULL;
    1975                     hrc = runSetUidToRootHelper(&strDisplayInfo,
    1976                                                 "uninstall",
    1977                                                 "--base-dir", m->strBaseDir.c_str(),
    1978                                                 "--name",     strName.c_str(),
    1979                                                 pszForcedOpt, /* Last as it may be NULL. */
    1980                                                 (const char *)NULL);
    1981                     if (SUCCEEDED(hrc))
    1982                     {
    1983                         hrc = refreshExtPack(strName.c_str(), false /*a_fUnusableIsError*/, &pExtPack);
    1984                         if (SUCCEEDED(hrc))
    1985                         {
    1986                             if (!pExtPack)
    1987                                 LogRel(("ExtPackManager: Successfully uninstalled extension pack '%s'.\n", strName.c_str()));
    1988                             else
    1989                                 hrc = setError(E_FAIL,
    1990                                                tr("Uninstall extension pack '%s' failed under mysterious circumstances"),
    1991                                                strName.c_str());
    1992                         }
    1993                     }
    1994                     else
    1995                     {
    1996                         ErrorInfoKeeper Eik;
    1997                         refreshExtPack(strName.c_str(), false /*a_fUnusableIsError*/, NULL);
    1998                     }
     2055                    pJob = NULL; /* the thread deletes it */
     2056                    ptrProgress.queryInterfaceTo(a_ppProgress);
    19992057                }
     2058                else
     2059                    hrc = setError(VBOX_E_IPRT_ERROR, tr("RTThreadCreate failed with %Rrc"), vrc);
    20002060            }
    20012061        }
    2002 
    2003         /*
    2004          * Do VirtualBoxReady callbacks now for any freshly installed
    2005          * extension pack (old ones will not be called).
    2006          */
    2007         if (m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON)
    2008         {
    2009             autoLock.release();
    2010             callAllVirtualBoxReadyHooks();
    2011         }
     2062        catch (std::bad_alloc)
     2063        {
     2064            hrc = E_OUTOFMEMORY;
     2065        }
     2066        if (pJob)
     2067            delete pJob;
    20122068    }
    20132069
     
    24722528
    24732529/**
     2530 * Thread wrapper around doInstall.
     2531 *
     2532 * @returns VINF_SUCCESS (ignored)
     2533 * @param   hThread             The thread handle (ignored).
     2534 * @param   pvJob               The job structure.
     2535 */
     2536/*static*/ DECLCALLBACK(int) ExtPackManager::doInstallThreadProc(RTTHREAD hThread, void *pvJob)
     2537{
     2538    PEXTPACKINSTALLJOB pJob = (PEXTPACKINSTALLJOB)pvJob;
     2539    HRESULT hrc = pJob->ptrExtPackMgr->doInstall(pJob->ptrExtPackFile, pJob->fReplace, &pJob->strDisplayInfo);
     2540    pJob->ptrProgress->notifyComplete(hrc);
     2541    delete pJob;
     2542
     2543    NOREF(hThread);
     2544    return VINF_SUCCESS;
     2545}
     2546
     2547/**
    24742548 * Worker for IExtPackFile::Install.
     2549 *
     2550 * Called on a worker thread via doInstallThreadProc.
    24752551 *
    24762552 * @returns COM status code.
     
    24832559 *                              be NULL.
    24842560 */
    2485 HRESULT ExtPackManager::doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace, Utf8Str const *a_pstrDisplayInfo,
    2486                                   IProgress **a_ppProgress)
     2561HRESULT ExtPackManager::doInstall(ExtPackFile *a_pExtPackFile, bool a_fReplace, Utf8Str const *a_pstrDisplayInfo)
    24872562{
    24882563    AssertReturn(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON, E_UNEXPECTED);
    24892564    iprt::MiniString const * const pStrName     = &a_pExtPackFile->m->Desc.strName;
    24902565    iprt::MiniString const * const pStrTarball  = &a_pExtPackFile->m->strExtPackFile;
    2491     NOREF(a_ppProgress); /** @todo implement progress object */
    24922566
    24932567    AutoCaller autoCaller(this);
     
    25802654}
    25812655
     2656/**
     2657 * Thread wrapper around doUninstall.
     2658 *
     2659 * @returns VINF_SUCCESS (ignored)
     2660 * @param   hThread             The thread handle (ignored).
     2661 * @param   pvJob               The job structure.
     2662 */
     2663/*static*/ DECLCALLBACK(int) ExtPackManager::doUninstallThreadProc(RTTHREAD hThread, void *pvJob)
     2664{
     2665    PEXTPACKUNINSTALLJOB pJob = (PEXTPACKUNINSTALLJOB)pvJob;
     2666    HRESULT hrc = pJob->ptrExtPackMgr->doUninstall(&pJob->strName, pJob->fForcedRemoval, &pJob->strDisplayInfo);
     2667    pJob->ptrProgress->notifyComplete(hrc);
     2668    delete pJob;
     2669
     2670    NOREF(hThread);
     2671    return VINF_SUCCESS;
     2672}
     2673
     2674/**
     2675 * Worker for IExtPackManager::Uninstall.
     2676 *
     2677 * Called on a worker thread via doUninstallThreadProc.
     2678 *
     2679 * @returns COM status code.
     2680 * @param   a_pstrName          The name of the extension pack to uninstall.
     2681 * @param   a_fForcedRemoval    Whether to be skip and ignore certain bits of
     2682 *                              the extpack feedback.  To deal with misbehaving
     2683 *                              extension pack hooks.
     2684 * @param   a_pstrDisplayInfo   Host specific display information hacks.
     2685 */
     2686HRESULT ExtPackManager::doUninstall(Utf8Str const *a_pstrName, bool a_fForcedRemoval, Utf8Str const *a_pstrDisplayInfo)
     2687{
     2688    Assert(m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON);
     2689
     2690    AutoCaller autoCaller(this);
     2691    HRESULT hrc = autoCaller.rc();
     2692    if (SUCCEEDED(hrc))
     2693    {
     2694        AutoWriteLock autoLock(this COMMA_LOCKVAL_SRC_POS);
     2695
     2696        /*
     2697         * Refresh the data we have on the extension pack as it may be made
     2698         * stale by direct meddling or some other user.
     2699         */
     2700        ExtPack *pExtPack;
     2701        hrc = refreshExtPack(a_pstrName->c_str(), false /*a_fUnusableIsError*/, &pExtPack);
     2702        if (SUCCEEDED(hrc))
     2703        {
     2704            if (!pExtPack)
     2705            {
     2706                LogRel(("ExtPackManager: Extension pack '%s' is not installed, so nothing to uninstall.\n", a_pstrName->c_str()));
     2707                hrc = S_OK;             /* nothing to uninstall */
     2708            }
     2709            else
     2710            {
     2711                /*
     2712                 * Call the uninstall hook and unload the main dll.
     2713                 */
     2714                hrc = pExtPack->callUninstallHookAndClose(m->pVirtualBox, a_fForcedRemoval);
     2715                if (SUCCEEDED(hrc))
     2716                {
     2717                    /*
     2718                     * Run the set-uid-to-root binary that performs the
     2719                     * uninstallation.  Then refresh the object.
     2720                     *
     2721                     * This refresh is theorically subject to races, but it's of
     2722                     * the don't-do-that variety.
     2723                     */
     2724                    const char *pszForcedOpt = a_fForcedRemoval ? "--forced" : NULL;
     2725                    hrc = runSetUidToRootHelper(a_pstrDisplayInfo,
     2726                                                "uninstall",
     2727                                                "--base-dir", m->strBaseDir.c_str(),
     2728                                                "--name",     a_pstrName->c_str(),
     2729                                                pszForcedOpt, /* Last as it may be NULL. */
     2730                                                (const char *)NULL);
     2731                    if (SUCCEEDED(hrc))
     2732                    {
     2733                        hrc = refreshExtPack(a_pstrName->c_str(), false /*a_fUnusableIsError*/, &pExtPack);
     2734                        if (SUCCEEDED(hrc))
     2735                        {
     2736                            if (!pExtPack)
     2737                                LogRel(("ExtPackManager: Successfully uninstalled extension pack '%s'.\n", a_pstrName->c_str()));
     2738                            else
     2739                                hrc = setError(E_FAIL,
     2740                                               tr("Uninstall extension pack '%s' failed under mysterious circumstances"),
     2741                                               a_pstrName->c_str());
     2742                        }
     2743                    }
     2744                    else
     2745                    {
     2746                        ErrorInfoKeeper Eik;
     2747                        refreshExtPack(a_pstrName->c_str(), false /*a_fUnusableIsError*/, NULL);
     2748                    }
     2749                }
     2750            }
     2751        }
     2752
     2753        /*
     2754         * Do VirtualBoxReady callbacks now for any freshly installed
     2755         * extension pack (old ones will not be called).
     2756         */
     2757        if (m->enmContext == VBOXEXTPACKCTX_PER_USER_DAEMON)
     2758        {
     2759            autoLock.release();
     2760            callAllVirtualBoxReadyHooks();
     2761        }
     2762    }
     2763
     2764    return hrc;
     2765}
     2766
    25822767
    25832768/**
  • trunk/src/VBox/Main/src-all/ExtPackUtil.cpp

    r35368 r35523  
    7777    a_pExtPackDesc->fShowLicense = false;
    7878}
     79
     80/**
     81 * Initializes an extension pack descriptor so that it's safe to call free on
     82 * it whatever happens later on.
     83 *
     84 * @param   a_pExtPackDesc  The descirptor to initialize.
     85 */
     86void VBoxExtPackInitDesc(PVBOXEXTPACKDESC a_pExtPackDesc)
     87{
     88    vboxExtPackClearDesc(a_pExtPackDesc);
     89}
     90
    7991
    8092/**
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