VirtualBox

Changeset 42923 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Aug 22, 2012 3:33:56 PM (12 years ago)
Author:
vboxsync
Message:

GuestSessionImplTasks/Update Additions: Get rid of the env var hacks, use guest properties to detect guest OS + installation paths, revamped code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r42918 r42923  
    2727#include "Global.h"
    2828#include "AutoCaller.h"
     29#include "ConsoleImpl.h"
     30#include "MachineImpl.h"
    2931#include "ProgressImpl.h"
    3032
     
    4143
    4244
    43 /*
    44  * If the following define is enabled the Guest Additions update code also
    45  * checks for locations which were not supposed to happen due to not resolving
    46  * environment variables in VBoxService toolbox arguments. So a file copied
    47  * to "%TEMP%\foo.exe" became "C:\Windows\EMPfoo.exe".
     45/*******************************************************************************
     46*   Defines                                                                    *
     47*******************************************************************************/
     48
     49/**
     50 * Update file flags.
    4851 */
    49 #define VBOX_SERVICE_ENVARG_BUG
     52#define UPDATEFILE_FLAG_NONE        RT_BIT(0)
     53/** File is optional, does not have to be
     54 *  existent on the .ISO. */
     55#define UPDATEFILE_FLAG_OPTIONAL    RT_BIT(1)
     56/** Execute file on the guest after it has
     57 *  been successfully transfered. */
     58#define UPDATEFILE_FLAG_EXECUTE     RT_BIT(2)
     59
    5060
    5161// session task classes
     
    5969GuestSessionTask::~GuestSessionTask(void)
    6070{
     71}
     72
     73int GuestSessionTask::getGuestProperty(const ComObjPtr<Guest> &pGuest,
     74                                       const Utf8Str &strPath, Utf8Str &strValue)
     75{
     76    ComObjPtr<Console> pConsole = pGuest->getConsole();
     77    const ComPtr<IMachine> pMachine = pConsole->machine();
     78
     79    Assert(!pMachine.isNull());
     80    Bstr strTemp, strFlags;
     81    LONG64 i64Timestamp;
     82    HRESULT hr = pMachine->GetGuestProperty(Bstr(strPath).raw(),
     83                                            strTemp.asOutParam(),
     84                                            &i64Timestamp, strFlags.asOutParam());
     85    if (SUCCEEDED(hr))
     86    {
     87        strValue = strTemp;
     88        return VINF_SUCCESS;
     89    }
     90    return VERR_NOT_FOUND;
     91
     92
    6193}
    6294
     
    729761            rc = pSession->startTaskAsync(Utf8StrFmt(GuestSession::tr("Copying Guest Additions installer file \"%s\" to \"%s\" on guest"),
    730762                                                     mSource.c_str(), strFileDest.c_str()),
    731                                           pTask, pProgressCopyTo);
     763                                                     pTask, pProgressCopyTo);
    732764            if (RT_SUCCESS(rc))
    733765            {
     
    759791        int64_t cbSizeOnGuest;
    760792        rc = pSession->fileQuerySizeInternal(strFileDest, &cbSizeOnGuest);
    761 #ifdef VBOX_SERVICE_ENVARG_BUG
    762         if (RT_FAILURE(rc))
    763         {
    764             /* Ugly hack: Because older Guest Additions have problems with environment variable
    765                           expansion in parameters we have to check an alternative location on Windows.
    766                           So check for "%TEMP%\" being "C:\\Windows\\system32\\EMP" actually. */
    767             if (strFileDest.startsWith("%TEMP%\\", RTCString::CaseSensitive))
    768             {
    769                 Utf8Str strFileDestBug = "C:\\Windows\\system32\\EMP" + strFileDest.substr(sizeof("%TEMP%\\") - sizeof(char));
    770                 rc = pSession->fileQuerySizeInternal(strFileDestBug, &cbSizeOnGuest);
    771             }
    772         }
    773 #endif
    774793        if (   RT_SUCCESS(rc)
    775794            && cbSize == (uint64_t)cbSizeOnGuest)
     
    781800        {
    782801            if (RT_SUCCESS(rc)) /* Size does not match. */
    783                 rc = VERR_BROKEN_PIPE; /** @todo FInd a better error. */
     802            {
     803                LogRel(("Size of Guest Additions installer file \"%s\" does not match: %RI64bytes copied, %RU64bytes expected\n",
     804                        strFileDest.c_str(), cbSizeOnGuest, cbSize));
     805                rc = VERR_BROKEN_PIPE; /** @todo Find a better error. */
     806            }
     807            else
     808                LogRel(("Error copying Guest Additions installer file \"%s\": %Rrc\n",
     809                        strFileDest.c_str(), rc));
    784810        }
    785811
     
    798824    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
    799825
    800 #ifdef VBOX_SERVICE_ENVARG_BUG
    801     GuestFsObjData objData;
    802     int rc = pSession->fileQueryInfoInternal(procInfo.mCommand, objData);
    803     if (RT_FAILURE(rc))
    804         procInfo.mCommand = "C:\\Windows\\system32\\EMP" + procInfo.mCommand.substr(sizeof("%TEMP%\\") - sizeof(char));
    805 #endif
    806 
    807826    ComObjPtr<GuestProcess> pProcess;
    808     rc = pSession->processCreateExInteral(procInfo, pProcess);
     827    int rc = pSession->processCreateExInteral(procInfo, pProcess);
    809828    if (RT_SUCCESS(rc))
    810829        rc = pProcess->startProcess();
     
    877896    /*
    878897     * Determine guest OS type and the required installer image.
    879      * At the moment only Windows guests are supported.
    880898     */
    881     Utf8Str strInstallerImage;
    882 
    883899    ComObjPtr<Guest> pGuest(mSession->getParent());
    884     Bstr osTypeId;
    885     if (   SUCCEEDED(pGuest->COMGETTER(OSTypeId(osTypeId.asOutParam())))
    886         && !osTypeId.isEmpty())
    887     {
    888         Utf8Str osTypeIdUtf8(osTypeId); /* Needed for .contains(). */
    889         if (   osTypeIdUtf8.contains("Microsoft", Utf8Str::CaseInsensitive)
    890             || osTypeIdUtf8.contains("Windows", Utf8Str::CaseInsensitive))
    891         {
    892             if (osTypeIdUtf8.contains("64", Utf8Str::CaseInsensitive))
    893                 strInstallerImage = "VBOXWINDOWSADDITIONS_AMD64.EXE";
    894             else
    895                 strInstallerImage = "VBOXWINDOWSADDITIONS_X86.EXE";
    896             /* Since the installers are located in the root directory,
    897              * no further path processing needs to be done (yet). */
    898         }
    899         else /* Everything else is not supported (yet). */
    900         {
    901             hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    902                                      Utf8StrFmt(GuestSession::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"),
    903                                      osTypeIdUtf8.c_str()));
    904             rc = VERR_GENERAL_FAILURE; /* Fudge. */
    905         }
    906     }
    907     else
     900
     901    eOSType eOSType;
     902    Utf8Str strOSType;
     903    rc = getGuestProperty(pGuest, "/VirtualBox/GuestInfo/OS/Product", strOSType);
     904    if (   strOSType.contains("Microsoft", Utf8Str::CaseInsensitive)
     905        || strOSType.contains("Windows", Utf8Str::CaseInsensitive))
     906    {
     907        eOSType = eOSType_Windows;
     908    }
     909    else if (strOSType.contains("Solaris", Utf8Str::CaseInsensitive))
     910    {
     911        eOSType = eOSType_Solaris;
     912    }
     913    else /* Everything else hopefully means Linux :-). */
     914        eOSType = eOSType_Linux;
     915
     916#if 1 /* Only Windows is supported (and tested) at the moment. */
     917    if (eOSType != eOSType_Windows)
    908918    {
    909919        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    910                                  Utf8StrFmt(GuestSession::tr("Could not detected guest OS type/version, please update manually")));
    911         rc = VERR_GENERAL_FAILURE; /* Fudge. */
    912     }
     920                                 Utf8StrFmt(GuestSession::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"),
     921                                            strOSType.c_str()));
     922        rc = VERR_NOT_SUPPORTED;
     923    }
     924#endif
    913925
    914926    RTISOFSFILE iso;
    915927    if (RT_SUCCESS(rc))
    916928    {
    917         Assert(!strInstallerImage.isEmpty());
    918 
    919929        /*
    920          * Try to open the .ISO file and locate the specified installer.
     930         * Try to open the .ISO file to extract all needed files.
    921931         */
    922932        rc = RTIsoFsOpen(&iso, mSource.c_str());
     
    929939        else
    930940        {
     941            /* Set default installation directories. */
     942            Utf8Str strInstallerDir = "/tmp/";
     943            if (eOSType == eOSType_Windows)
     944                 strInstallerDir = "C:\\Temp\\";
     945
    931946            rc = setProgress(5);
    932947
    933             /** @todo Add support for non-Windows as well! */
    934             Utf8Str strInstallerDest = "%TEMP%\\VBoxWindowsAdditions.exe";
    935             bool fInstallCertificates = false;
    936 
     948            /* Try looking up the Guest Additions installation directory. */
    937949            if (RT_SUCCESS(rc))
    938950            {
    939                 /*
    940                  * Copy over main installer to the guest.
    941                  */
    942                 rc = copyFileToGuest(pSession, &iso, strInstallerImage, strInstallerDest,
    943                                      false /* File is not optional */, NULL /* cbSize */);
     951                rc = getGuestProperty(pGuest, "/VirtualBox/GuestAdd/InstallDir", strInstallerDir);
    944952                if (RT_SUCCESS(rc))
    945                     rc = setProgress(20);
    946 
    947                 /*
    948                  * Install needed certificates for the WHQL crap.
    949                  ** @todo Only for Windows!
    950                  */
     953                {
     954                    LogRel(("Guest Additions were installed to: %ls\n",
     955                            strInstallerDir.c_str()));
     956                    rc = setProgress(8);
     957                }
     958
    951959                if (RT_SUCCESS(rc))
    952960                {
    953                     rc = copyFileToGuest(pSession, &iso, "CERT/ORACLE_VBOX.CER", "%TEMP%\\oracle-vbox.cer",
    954                                          true /* File is optional */, NULL /* cbSize */);
    955                     if (RT_SUCCESS(rc))
     961                    if (eOSType == eOSType_Windows)
    956962                    {
    957                         rc = setProgress(30);
    958                         if (RT_SUCCESS(rc))
    959                         {
    960                             rc = copyFileToGuest(pSession, &iso, "CERT/VBOXCERTUTIL.EXE", "%TEMP%\\VBoxCertUtil.exe",
    961                                                  true /* File is optional */, NULL /* cbSize */);
    962                             if (RT_SUCCESS(rc))
    963                             {
    964                                 fInstallCertificates = true;
    965                                 rc = setProgress(40);
    966                             }
    967                             else
    968                                 hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    969                                                          Utf8StrFmt(GuestSession::tr("Error while copying certificate installation tool to the guest: %Rrc"), rc));
    970                         }
     963                        strInstallerDir.findReplace('/', '\\');
     964                        strInstallerDir.append("\\Update\\");
    971965                    }
    972966                    else
     967                        strInstallerDir.append("/update/");
     968                }
     969            }
     970
     971            LogRel(("Guest Additions update will be installed to: %s\n",
     972                    strInstallerDir.c_str()));
     973
     974            /* Prepare the file(s) we want to copy over to the guest and
     975             * (maybe) want to run. */
     976            switch (eOSType)
     977            {
     978                case eOSType_Windows:
     979                {
     980                    /* Our certificate. */
     981                    mFiles.push_back(InstallerFile("CERT/ORACLE_VBOX.CER",  "Oracle_VBox.cer",
     982                                                   UPDATEFILE_FLAG_OPTIONAL));
     983                    /* Our certificate installation utility. */
     984                    GuestProcessStartupInfo siCertUtil;
     985                    siCertUtil.mArguments.push_back(Utf8Str("add-trusted-publisher"));
     986                    siCertUtil.mArguments.push_back(Utf8Str(strInstallerDir + "oracle-vbox.cer"));
     987                    mFiles.push_back(InstallerFile("CERT/VBOXCERTUTIL.EXE", "VBoxCertUtil.exe",
     988                                                   UPDATEFILE_FLAG_OPTIONAL | UPDATEFILE_FLAG_EXECUTE, siCertUtil));
     989                    /* The installers in different flavors. */
     990                    mFiles.push_back(InstallerFile("VBOXWINDOWSADDITIONS_X86.EXE",
     991                                                   strInstallerDir + "VBoxWindowsAdditions_x86.exe",
     992                                                   UPDATEFILE_FLAG_NONE));
     993                    mFiles.push_back(InstallerFile("VBOXWINDOWSADDITIONS_AMD64.EXE",
     994                                                   strInstallerDir + "VBoxWindowsAdditions_amd64.exe",
     995                                                   UPDATEFILE_FLAG_NONE));
     996                    GuestProcessStartupInfo siInstaller;
     997                    siInstaller.mArguments.push_back(Utf8Str("/S")); /* We want to install in silent mode. */
     998                    siInstaller.mArguments.push_back(Utf8Str("/l")); /* ... and logging enabled. */
     999                    /* Don't quit VBoxService during upgrade because it still is used for this
     1000                     * piece of code we're in right now (that is, here!) ... */
     1001                    siInstaller.mArguments.push_back(Utf8Str("/no_vboxservice_exit"));
     1002                    /* Tell the installer to report its current installation status
     1003                     * using a running VBoxTray instance via balloon messages in the
     1004                     * Windows taskbar. */
     1005                    siInstaller.mArguments.push_back(Utf8Str("/post_installstatus"));
     1006                    /* If the caller does not want to wait for out guest update process to end,
     1007                     * complete the progress object now so that the caller can do other work. */
     1008                    if (mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly)
     1009                        siInstaller.mFlags |= ProcessCreateFlag_WaitForProcessStartOnly;
     1010                    mFiles.push_back(InstallerFile("VBOXWINDOWSADDITIONS.EXE",
     1011                                                   strInstallerDir + "VBoxWindowsAdditions.exe",
     1012                                                   UPDATEFILE_FLAG_EXECUTE, siInstaller));
     1013                    break;
     1014                }
     1015                case eOSType_Linux:
     1016                    /** @todo Add Linux support. */
     1017                    break;
     1018                case eOSType_Solaris:
     1019                    /** @todo Add Solaris support. */
     1020                    break;
     1021                default:
     1022                    rc = VERR_INVALID_PARAMETER;
     1023            }
     1024
     1025            if (RT_SUCCESS(rc))
     1026            {
     1027                std::vector<InstallerFile>::const_iterator itFiles = mFiles.begin();
     1028                while (itFiles != mFiles.end())
     1029                {
     1030                    rc = copyFileToGuest(pSession, &iso, itFiles->strSource, itFiles->strDest,
     1031                                         (itFiles->fFlags & UPDATEFILE_FLAG_OPTIONAL), NULL /* cbSize */);
     1032                    if (RT_FAILURE(rc))
     1033                    {
    9731034                        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    974                                                  Utf8StrFmt(GuestSession::tr("Error while copying certificate to the guest: %Rrc"), rc));
    975                 }
    976             }
    977 
    978             /*
    979              * Run VBoxCertUtil.exe to install the Oracle certificate.
    980              */
    981             if (   RT_SUCCESS(rc)
    982                 && fInstallCertificates)
    983             {
    984                 LogRel(("Installing certificates on the guest ...\n"));
    985 
    986                 GuestProcessStartupInfo procInfo;
    987                 procInfo.mName    = Utf8StrFmt(GuestSession::tr("VirtualBox Guest Additions Certificate Utility"));
    988                 procInfo.mCommand = Utf8Str("%TEMP%\\VBoxCertUtil.exe");
    989                 procInfo.mFlags   = ProcessCreateFlag_Hidden;
    990 
    991                 /* Construct arguments. */
    992                 /** @todo Remove hardcoded paths. */
    993                 procInfo.mArguments.push_back(Utf8Str("add-trusted-publisher"));
    994                 /* Ugly hack: Because older Guest Additions have problems with environment variable
    995                           expansion in parameters we have to check an alternative location on Windows.
    996                           So check for "%TEMP%\VBoxWindowsAdditions.exe" in a screwed up way. */
    997 #ifdef VBOX_SERVICE_ENVARG_BUG
    998                 GuestFsObjData objData;
    999                 rc = pSession->fileQueryInfoInternal("%TEMP%\\oracle-vbox.cer", objData);
    1000                 if (RT_SUCCESS(rc))
    1001 #endif
    1002                     procInfo.mArguments.push_back(Utf8Str("%TEMP%\\oracle-vbox.cer"));
    1003 #ifdef VBOX_SERVICE_ENVARG_BUG
    1004                 else
    1005                     procInfo.mArguments.push_back(Utf8Str("C:\\Windows\\system32\\EMPoracle-vbox.cer"));
    1006 #endif
    1007                 /* Overwrite rc in any case. */
    1008                 rc = runFile(pSession, procInfo);
     1035                                                  Utf8StrFmt(GuestSession::tr("Error while copying file \"%s\" to \"%s\" on the guest: %Rrc"),
     1036                                                             itFiles->strSource, itFiles->strDest, rc));
     1037                        break;
     1038                    }
     1039                    itFiles++;
     1040                }
    10091041            }
    10101042
    10111043            if (RT_SUCCESS(rc))
    1012                 rc = setProgress(60);
     1044            {
     1045                std::vector<InstallerFile>::iterator itFiles = mFiles.begin();
     1046                while (itFiles != mFiles.end())
     1047                {
     1048                    rc = runFile(pSession, itFiles->mProcInfo);
     1049                    if (RT_FAILURE(rc))
     1050                    {
     1051                        hr = setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     1052                                                  Utf8StrFmt(GuestSession::tr("Error while running installer file \"%s\" on the guest: %Rrc"),
     1053                                                             itFiles->strDest, rc));
     1054                        break;
     1055                    }
     1056                    itFiles++;
     1057                }
     1058            }
    10131059
    10141060            if (RT_SUCCESS(rc))
    1015             {
    1016                 LogRel(("Updating Guest Additions ...\n"));
    1017 
    1018                 GuestProcessStartupInfo procInfo;
    1019                 procInfo.mName    = Utf8StrFmt(GuestSession::tr("VirtualBox Guest Additions Setup"));
    1020                 procInfo.mCommand = Utf8Str(strInstallerDest);
    1021                 procInfo.mFlags   = ProcessCreateFlag_Hidden;
    1022                 /* If the caller does not want to wait for out guest update process to end,
    1023                  * complete the progress object now so that the caller can do other work. */
    1024                 if (mFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly)
    1025                     procInfo.mFlags |= ProcessCreateFlag_WaitForProcessStartOnly;
    1026 
    1027                 /* Construct arguments. */
    1028                 procInfo.mArguments.push_back(Utf8Str("/S")); /* We want to install in silent mode. */
    1029                 procInfo.mArguments.push_back(Utf8Str("/l")); /* ... and logging enabled. */
    1030                 /* Don't quit VBoxService during upgrade because it still is used for this
    1031                  * piece of code we're in right now (that is, here!) ... */
    1032                 procInfo.mArguments.push_back(Utf8Str("/no_vboxservice_exit"));
    1033                 /* Tell the installer to report its current installation status
    1034                  * using a running VBoxTray instance via balloon messages in the
    1035                  * Windows taskbar. */
    1036                 procInfo.mArguments.push_back(Utf8Str("/post_installstatus"));
    1037 
    1038                 rc = runFile(pSession, procInfo);
    1039                 if (RT_SUCCESS(rc))
    1040                     hr = setProgressSuccess();
    1041             }
     1061                hr = setProgressSuccess();
     1062
    10421063            RTIsoFsClose(&iso);
    10431064        }
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