VirtualBox

Changeset 104162 in vbox for trunk/src/VBox/Installer


Ignore:
Timestamp:
Apr 4, 2024 5:05:37 PM (11 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
162588
Message:

Windows/Host Installer: Check permissions of target directory when installing. Added a new testcase for this. bugref:10616

Location:
trunk/src/VBox/Installer/win
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp

    r103676 r104162  
    3939#include <iprt/utf16.h>
    4040
     41#include "VBoxCommon.h"
    4142
     43
     44#ifndef TESTCASE
     45/**
     46 * Retrieves a MSI property (in UTF-16).
     47 *
     48 * Convenience function for VBoxGetMsiProp().
     49 *
     50 * @returns VBox status code.
     51 * @param   hMsi                MSI handle to use.
     52 * @param   pwszName            Name of property to retrieve.
     53 * @param   pwszValueBuf        Where to store the allocated value on success.
     54 * @param   cwcValueBuf         Size (in WCHARs) of \a pwszValueBuf.
     55 */
    4256UINT VBoxGetMsiProp(MSIHANDLE hMsi, const WCHAR *pwszName, WCHAR *pwszValueBuf, DWORD cwcValueBuf)
    4357{
    44     RT_BZERO(pwszValueBuf, cwcValueBuf * sizeof(pwszValueBuf[0]));
     58    RT_BZERO(pwszValueBuf, cwcValueBuf * sizeof(WCHAR));
     59    return MsiGetPropertyW(hMsi, pwszName, pwszValueBuf, &cwcValueBuf);
     60}
     61#endif
    4562
    46     /** @todo r=bird: why do we need to query the size first and then the data.
    47      *        The API should be perfectly capable of doing that without our help. */
    48     WCHAR wcDummy   = 0;
    49     DWORD cwcNeeded = 0;
    50     UINT  uiRet = MsiGetPropertyW(hMsi, pwszName, &wcDummy, &cwcNeeded);
    51     if (uiRet == ERROR_MORE_DATA)
    52     {
    53         ++cwcNeeded;     /* On output does not include terminating null, so add 1. */
    54 
    55         if (cwcNeeded > cwcValueBuf)
    56             return ERROR_MORE_DATA;
    57         uiRet = MsiGetPropertyW(hMsi, pwszName, pwszValueBuf, &cwcNeeded);
    58     }
    59     return uiRet;
    60 }
    61 
    62 #if 0 /* unused */
    6363/**
    6464 * Retrieves a MSI property (in UTF-8).
     
    8989    return rc;
    9090}
    91 #endif
    9291
     92#ifndef TESTCASE
    9393UINT VBoxSetMsiProp(MSIHANDLE hMsi, const WCHAR *pwszName, const WCHAR *pwszValue)
    9494{
    9595    return MsiSetPropertyW(hMsi, pwszName, pwszValue);
    9696}
     97#endif
    9798
    9899UINT VBoxSetMsiPropDWORD(MSIHANDLE hMsi, const WCHAR *pwszName, DWORD dwVal)
  • trunk/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp

    r103889 r104162  
    3838#include <iprt/win/windows.h>
    3939
     40#include <aclapi.h>
    4041#include <msi.h>
    4142#include <msiquery.h>
     
    4647#include <cfgmgr32.h>
    4748#include <devguid.h>
     49#include <sddl.h> /* For ConvertSidToStringSidW. */
    4850
    4951#include <iprt/win/objbase.h>
     
    5557#include <iprt/assert.h>
    5658#include <iprt/alloca.h>
     59#include <iprt/dir.h>
     60#include <iprt/err.h>
     61#include <iprt/file.h>
    5762#include <iprt/mem.h>
    5863#include <iprt/path.h>   /* RTPATH_MAX, RTPATH_IS_SLASH */
    5964#include <iprt/string.h> /* RT_ZERO */
     65#include <iprt/stream.h>
     66#include <iprt/thread.h>
    6067#include <iprt/utf16.h>
    6168
     
    7986
    8087
     88/*********************************************************************************************************************************
     89*   Internal structures                                                                                                          *
     90*********************************************************************************************************************************/
     91/**
     92 * Structure for keeping a target's directory security context.
     93 */
     94typedef struct TGTDIRSECCTX
     95{
     96    /** Initialized status. */
     97    bool     fInitialized;
     98    /** Handle of the target's parent directory.
     99     *
     100     * Kept open while the context is around and initialized. */
     101    RTDIR    hParentDir;
     102    /** Absolute (resolved) path of the target directory. */
     103    char     szTargetDirAbs[RTPATH_MAX];
     104    /** Access mask which is forbidden for an ACE of type ACCESS_ALLOWED_ACE_TYPE. */
     105    uint32_t fAccessMaskForbidden;
     106    /** Array of well-known SIDs which are forbidden. */
     107    PSID    *paWellKnownSidsForbidden;
     108    /** Number of entries in \a paWellKnownSidsForbidden. */
     109    size_t   cWellKnownSidsForbidden;
     110} TGTDIRSECCTX;
     111/** Pointer to a target's directory security context. */
     112typedef TGTDIRSECCTX *PTGTDIRSECCTX;
     113
     114
     115/*********************************************************************************************************************************
     116*   Prototypes                                                                                                                   *
     117*********************************************************************************************************************************/
     118static void destroyTargetDirSecurityCtx(PTGTDIRSECCTX pCtx);
     119
     120
     121/*********************************************************************************************************************************
     122*   Globals                                                                                                                      *
     123*********************************************************************************************************************************/
     124static uint32_t     g_cRef = 0;
     125/** Our target directory security context.
     126 *
     127 * Has to be global in order to keep it around as long as the DLL is being loaded. */
     128static TGTDIRSECCTX g_TargetDirSecCtx = { 0 };
     129
    81130
    82131/**
     
    87136    RT_NOREF(hInst, uReason, pReserved);
    88137
     138#ifdef DEBUG
     139    WCHAR wszMsg[128];
     140    RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "DllMain: hInst=%#x, uReason=%u (PID %u), g_cRef=%RU32\n",
     141                  hInst, uReason, GetCurrentProcessId(), g_cRef);
     142    OutputDebugStringW(wszMsg);
     143#endif
     144
     145    switch (uReason)
     146    {
     147        case DLL_PROCESS_ATTACH:
     148        {
     149            g_cRef++;
    89150#if 0
    90     /*
    91      * This is a trick for allowing the debugger to be attached, don't know if
    92      * there is an official way to do that, but this is a pretty efficient.
    93      *
    94      * Monitor the debug output in DbgView and be ready to start windbg when
    95      * the message below appear.  This will happen 3-4 times during install,
    96      * and 2-3 times during uninstall.
    97      *
    98      * Note! The DIFxApp.DLL will automatically trigger breakpoints when a
    99      *       debugger is attached.  Just continue on these.
    100      */
    101     if (uReason == DLL_PROCESS_ATTACH)
    102     {
    103         WCHAR wszMsg[128];
    104         RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "Waiting for debugger to attach: windbg -g -G -p %u\n", GetCurrentProcessId());
    105         for (unsigned i = 0; i < 128 && !IsDebuggerPresent(); i++)
    106         {
    107             OutputDebugStringW(wszMsg);
    108             Sleep(1001);
    109         }
    110         Sleep(1002);
    111         __debugbreak();
    112     }
     151            /*
     152             * This is a trick for allowing the debugger to be attached, don't know if
     153             * there is an official way to do that, but this is a pretty efficient.
     154             *
     155             * Monitor the debug output in DbgView and be ready to start windbg when
     156             * the message below appear.  This will happen 3-4 times during install,
     157             * and 2-3 times during uninstall.
     158             *
     159             * Note! The DIFxApp.DLL will automatically trigger breakpoints when a
     160             *       debugger is attached.  Just continue on these.
     161             */
     162            RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "Waiting for debugger to attach: windbg -g -G -p %u\n", GetCurrentProcessId());
     163            for (unsigned i = 0; i < 128 && !IsDebuggerPresent(); i++)
     164            {
     165                OutputDebugStringW(wszMsg);
     166                Sleep(1001);
     167            }
     168            Sleep(1002);
     169            __debugbreak();
    113170#endif
     171            break;
     172        }
     173
     174        case DLL_PROCESS_DETACH:
     175        {
     176            g_cRef--;
     177            break;
     178        }
     179
     180        default:
     181            break;
     182    }
    114183
    115184    return TRUE;
     
    117186
    118187/**
    119  * Format and add message to the MSI log.
     188 * Format a log message and print it to whatever is there (i.e. to the MSI log).
    120189 *
    121190 * UTF-16 strings are formatted using '%ls' (lowercase).
    122191 * ANSI strings are formatted using '%s' (uppercase).
     192 *
     193 * @returns VBox status code.
     194 * @param   hInstall            MSI installer handle. Optional and can be NULL.
     195 * @param   pszFmt              Format string.
     196 * @param   ...                 Variable arguments for format string.
    123197 */
    124 static UINT logStringF(MSIHANDLE hInstall, const char *pszFmt, ...)
    125 {
     198static int logStringF(MSIHANDLE hInstall, const char *pszFmt, ...)
     199{
     200    RTUTF16 wszVa[RTPATH_MAX + 256];
     201    va_list va;
     202    va_start(va, pszFmt);
     203    ssize_t cwc = RTUtf16PrintfV(wszVa, RT_ELEMENTS(wszVa), pszFmt, va);
     204    va_end(va);
     205
     206    RTUTF16 wszMsg[RTPATH_MAX + 256];
     207    cwc = RTUtf16Printf(wszMsg, sizeof(wszMsg), "VBoxInstallHelper: %ls", wszVa);
     208    if (cwc <= 0)
     209        return VERR_BUFFER_OVERFLOW;
     210
     211#ifdef DEBUG
     212    OutputDebugStringW(wszMsg);
     213#endif
     214#ifdef TESTCASE
     215    RTPrintf("%ls\n", wszMsg);
     216#endif
    126217    PMSIHANDLE hMSI = MsiCreateRecord(2 /* cParms */);
    127218    if (hMSI)
    128219    {
    129         wchar_t wszBuf[RTPATH_MAX + 256];
    130         va_list va;
    131         va_start(va, pszFmt);
    132         ssize_t cwc = RTUtf16PrintfV(wszBuf, RT_ELEMENTS(wszBuf), pszFmt, va);
    133         va_end(va);
    134 
    135         MsiRecordSetStringW(hMSI, 0, wszBuf);
     220        MsiRecordSetStringW(hMSI, 0, wszMsg);
    136221        MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), hMSI);
    137 
    138222        MsiCloseHandle(hMSI);
    139         return cwc < RT_ELEMENTS(wszBuf) ? ERROR_SUCCESS : ERROR_BUFFER_OVERFLOW;
    140     }
    141     return ERROR_ACCESS_DENIED;
     223    }
     224
     225    return cwc < RT_ELEMENTS(wszVa) ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW;
    142226}
    143227
     
    160244#endif
    161245    return ERROR_SUCCESS;
     246}
     247
     248/**
     249 * Initializes a target security context.
     250 *
     251 * @returns VBox status code.
     252 * @param   pCtx                Target directory security context to initialize.
     253 * @param   hModule             Windows installer module handle.
     254 * @param   pszPath             Target directory path to use.
     255 */
     256static int initTargetDirSecurityCtx(PTGTDIRSECCTX pCtx, MSIHANDLE hModule, const char *pszPath)
     257{
     258    if (pCtx->fInitialized)
     259        return VINF_SUCCESS;
     260
     261#ifdef DEBUG
     262    logStringF(hModule, "initTargetDirSecurityCtx: pszPath=%s\n", pszPath);
     263#endif
     264
     265    char szPathTemp[RTPATH_MAX];
     266    int vrc = RTStrCopy(szPathTemp, sizeof(szPathTemp), pszPath);
     267    if (RT_FAILURE(vrc))
     268        return vrc;
     269
     270    /* Try to find a parent path which exists. */
     271    char szPathParentAbs[RTPATH_MAX] = { 0 };
     272    for (int i = 0; i < 256; i++) /* Failsafe counter. */
     273    {
     274        RTPathStripTrailingSlash(szPathTemp);
     275        RTPathStripFilename(szPathTemp);
     276        vrc = RTPathReal(szPathTemp, szPathParentAbs, sizeof(szPathParentAbs));
     277        if (RT_SUCCESS(vrc))
     278            break;
     279    }
     280
     281    if (RT_FAILURE(vrc))
     282    {
     283        logStringF(hModule, "initTargetDirSecurityCtx: No existing / valid parent directory found (%Rrc), giving up\n", vrc);
     284        return vrc;
     285    }
     286
     287    RTDIR hParentDir;
     288    vrc = RTDirOpen(&hParentDir, szPathParentAbs);
     289    if (RT_FAILURE(vrc))
     290    {
     291        logStringF(hModule, "initTargetDirSecurityCtx: Locking parent directory '%s' failed with %Rrc\n", szPathParentAbs, vrc);
     292        return vrc;
     293    }
     294
     295#ifdef DEBUG
     296    logStringF(hModule, "initTargetDirSecurityCtx: Locked parent directory '%s'\n", szPathParentAbs);
     297#endif
     298
     299    char szPathTargetAbs[RTPATH_MAX];
     300    vrc = RTPathReal(pszPath, szPathTargetAbs, sizeof(szPathTargetAbs));
     301    if (RT_FAILURE(vrc))
     302        vrc = RTStrCopy(szPathTargetAbs, sizeof(szPathTargetAbs), pszPath);
     303    if (RT_FAILURE(vrc))
     304    {
     305        logStringF(hModule, "initTargetDirSecurityCtx: Failed to resolve absolute target path (%Rrc)\n", vrc);
     306        return vrc;
     307    }
     308
     309#ifdef DEBUG
     310    logStringF(hModule, "initTargetDirSecurityCtx: szPathTargetAbs=%s, szPathParentAbs=%s\n", szPathTargetAbs, szPathParentAbs);
     311#endif
     312
     313    /* Target directory validation. */
     314    if (   !RTStrCmp(szPathTargetAbs, szPathParentAbs) /* Don't allow installation into root directories. */
     315        ||  RTStrStr(szPathTargetAbs, ".."))
     316    {
     317        logStringF(hModule, "initTargetDirSecurityCtx: Directory '%s' invalid", szPathTargetAbs);
     318        vrc = VERR_INVALID_NAME;
     319    }
     320
     321    if (RT_SUCCESS(vrc))
     322    {
     323        RTFSOBJINFO fsObjInfo;
     324        vrc = RTPathQueryInfo(szPathParentAbs, &fsObjInfo, RTFSOBJATTRADD_NOTHING);
     325        if (RT_SUCCESS(vrc))
     326        {
     327            if (RTFS_IS_DIRECTORY(fsObjInfo.Attr.fMode)) /* No symlinks or other fun stuff. */
     328            {
     329                static WELL_KNOWN_SID_TYPE aForbiddenWellKnownSids[] =
     330                {
     331                    WinNullSid,
     332                    WinWorldSid,
     333                    WinAuthenticatedUserSid,
     334                    WinBuiltinUsersSid,
     335                    WinBuiltinGuestsSid,
     336                    WinBuiltinPowerUsersSid
     337                };
     338
     339                pCtx->paWellKnownSidsForbidden = (PSID *)RTMemAlloc(sizeof(PSID) * RT_ELEMENTS(aForbiddenWellKnownSids));
     340                AssertPtrReturn(pCtx->paWellKnownSidsForbidden, VERR_NO_MEMORY);
     341
     342                size_t i = 0;
     343                for(; i < RT_ELEMENTS(aForbiddenWellKnownSids); i++)
     344                {
     345                    pCtx->paWellKnownSidsForbidden[i] = RTMemAlloc(SECURITY_MAX_SID_SIZE);
     346                    AssertPtrBreakStmt(pCtx->paWellKnownSidsForbidden, vrc = VERR_NO_MEMORY);
     347                    DWORD cbSid = SECURITY_MAX_SID_SIZE;
     348                    if (!CreateWellKnownSid(aForbiddenWellKnownSids[i], NULL, pCtx->paWellKnownSidsForbidden[i], &cbSid))
     349                    {
     350                        vrc = RTErrConvertFromWin32(GetLastError());
     351                        logStringF(hModule, "initTargetDirSecurityCtx: Creating SID (index %zu) failed with %Rrc\n", i, vrc);
     352                        break;
     353                    }
     354                }
     355
     356                if (RT_SUCCESS(vrc))
     357                {
     358                    vrc = RTStrCopy(pCtx->szTargetDirAbs, sizeof(pCtx->szTargetDirAbs), szPathTargetAbs);
     359                    if (RT_SUCCESS(vrc))
     360                    {
     361                        pCtx->fInitialized            = true;
     362                        pCtx->hParentDir              = hParentDir;
     363                        pCtx->cWellKnownSidsForbidden = i;
     364                        pCtx->fAccessMaskForbidden    = FILE_WRITE_DATA
     365                                                      | FILE_APPEND_DATA
     366                                                      | FILE_WRITE_ATTRIBUTES
     367                                                      | FILE_WRITE_EA;
     368
     369                        RTFILE fh;
     370                        RTFileOpen(&fh, "c:\\temp\\targetdir.ctx", RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE);
     371                        RTFileClose(fh);
     372
     373                        return VINF_SUCCESS;
     374                    }
     375                }
     376            }
     377            else
     378                vrc = VERR_INVALID_NAME;
     379        }
     380    }
     381
     382    RTDirClose(hParentDir);
     383
     384    while (pCtx->cWellKnownSidsForbidden--)
     385    {
     386        RTMemFree(pCtx->paWellKnownSidsForbidden[pCtx->cWellKnownSidsForbidden]);
     387        pCtx->paWellKnownSidsForbidden[pCtx->cWellKnownSidsForbidden] = NULL;
     388    }
     389
     390    logStringF(hModule, "initTargetDirSecurityCtx: Initialization failed failed with %Rrc\n", vrc);
     391    return vrc;
     392}
     393
     394/**
     395 * Destroys a target security context.
     396 *
     397 * @returns VBox status code.
     398 * @param   pCtx                Target directory security context to destroy.
     399 */
     400static void destroyTargetDirSecurityCtx(PTGTDIRSECCTX pCtx)
     401{
     402    if (   !pCtx
     403        || !pCtx->fInitialized)
     404        return;
     405
     406    if (pCtx->hParentDir != NIL_RTDIR)
     407    {
     408        RTDirClose(pCtx->hParentDir);
     409        pCtx->hParentDir = NIL_RTDIR;
     410    }
     411    RT_ZERO(pCtx->szTargetDirAbs);
     412
     413    for (size_t i = 0; i < pCtx->cWellKnownSidsForbidden; i++)
     414        RTMemFree(pCtx->paWellKnownSidsForbidden[i]);
     415    pCtx->cWellKnownSidsForbidden = 0;
     416
     417    RTMemFree(pCtx->paWellKnownSidsForbidden);
     418    pCtx->paWellKnownSidsForbidden = NULL;
     419
     420    RTFileDelete("c:\\temp\\targetdir.ctx");
     421
     422    logStringF(NULL, "destroyTargetDirSecurityCtx\n");
     423}
     424
     425#ifdef DEBUG
     426/**
     427 * Returns a stingified version of an ACE type.
     428 *
     429 * @returns Stingified version of an ACE type.
     430 * @param   uType               ACE type.
     431 */
     432inline const char *dbgAceTypeToString(uint8_t uType)
     433{
     434    switch (uType)
     435    {
     436        RT_CASE_RET_STR(ACCESS_ALLOWED_ACE_TYPE);
     437        RT_CASE_RET_STR(ACCESS_DENIED_ACE_TYPE);
     438        RT_CASE_RET_STR(SYSTEM_AUDIT_ACE_TYPE);
     439        RT_CASE_RET_STR(SYSTEM_ALARM_ACE_TYPE);
     440        default: break;
     441    }
     442
     443    return "<Invalid>";
     444}
     445
     446/**
     447 * Returns an allocated string for a SID containing the user/domain name.
     448 *
     449 * @returns Allocated string (UTF-8). Must be free'd using RTStrFree().
     450 * @param   pSid                SID to return allocated string for.
     451 */
     452inline char *dbgSidToNameA(const PSID pSid)
     453{
     454    char *pszName = NULL;
     455    int   vrc     = VINF_SUCCESS;
     456
     457    LPWSTR pwszSid = NULL;
     458    if (ConvertSidToStringSid(pSid, &pwszSid))
     459    {
     460        SID_NAME_USE SidNameUse;
     461
     462        WCHAR wszUser[MAX_PATH];
     463        DWORD cbUser   = sizeof(wszUser);
     464        WCHAR wszDomain[MAX_PATH];
     465        DWORD cbDomain = sizeof(wszDomain);
     466        if (LookupAccountSid(NULL, pSid, wszUser, &cbUser, wszDomain, &cbDomain, &SidNameUse))
     467        {
     468            RTUTF16 wszName[RTPATH_MAX];
     469            if (RTUtf16Printf(wszName, RT_ELEMENTS(wszName), "%ls%s%ls (%ls)",
     470                              wszUser, wszDomain[0] == L'\0' ? "" : "\\", wszDomain, pwszSid))
     471            {
     472                vrc = RTUtf16ToUtf8(wszName, &pszName);
     473            }
     474            else
     475                vrc = VERR_NO_MEMORY;
     476        }
     477        else
     478            vrc = RTStrAPrintf(&pszName, "<Lookup Error>");
     479
     480        LocalFree(pwszSid);
     481    }
     482    else
     483        vrc = VERR_NOT_FOUND;
     484
     485    return RT_SUCCESS(vrc) ? pszName : "<Invalid>";
     486}
     487#endif /* DEBUG */
     488
     489/**
     490 * Checks a single target path whether it's safe to use or not.
     491 *
     492 * We check if the given path is owned by "NT Service\TrustedInstaller" and therefore assume that it's safe to use.
     493 *
     494 * @returns VBox status code. On error the path should be considered unsafe.
     495 * @retval  VERR_INVALID_NAME if the given path is considered unsafe.
     496 * @retval  VINF_SUCCESS if the given path is found to be safe to use.
     497 * @param   hModule             Windows installer module handle.
     498 * @param   pszPath             Path to check.
     499 */
     500static int checkTargetDirOne(MSIHANDLE hModule, PTGTDIRSECCTX pCtx, const char *pszPath)
     501{
     502    logStringF(hModule, "checkTargetDirOne: Checking '%s' ...", pszPath);
     503
     504    PRTUTF16 pwszPath;
     505    int vrc = RTStrToUtf16(pszPath, &pwszPath);
     506    if (RT_FAILURE(vrc))
     507        return vrc;
     508
     509    PACL      pDacl = NULL;
     510    PSECURITY_DESCRIPTOR pSecurityDescriptor = { 0 };
     511    DWORD dwErr = GetNamedSecurityInfo(pwszPath, SE_FILE_OBJECT, GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
     512                                       NULL, NULL, NULL, NULL, &pSecurityDescriptor);
     513    if (dwErr == ERROR_SUCCESS)
     514    {
     515        BOOL fDaclPresent          = FALSE;
     516        BOOL fDaclDefaultedIgnored = FALSE;
     517        if (GetSecurityDescriptorDacl(pSecurityDescriptor, &fDaclPresent,
     518                                      &pDacl, &fDaclDefaultedIgnored))
     519        {
     520            if (   !fDaclPresent
     521                || !pDacl)
     522            {
     523                /* Bail out early if the DACL isn't provided or is missing. */
     524                vrc = VERR_INVALID_NAME;
     525            }
     526            else
     527            {
     528                ACL_SIZE_INFORMATION aclSizeInfo;
     529                RT_ZERO(aclSizeInfo);
     530                if (GetAclInformation(pDacl, &aclSizeInfo, sizeof(aclSizeInfo), AclSizeInformation))
     531                {
     532                    for(DWORD idxACE = 0; idxACE < aclSizeInfo.AceCount; idxACE++)
     533                    {
     534                        ACE_HEADER *pAceHdr = NULL;
     535                        if (GetAce(pDacl, idxACE, (LPVOID *)&pAceHdr))
     536                        {
     537#ifdef DEBUG
     538                            logStringF(hModule, "checkTargetDirOne: ACE type=%s, flags=%#x, size=%#x",
     539                                       dbgAceTypeToString(pAceHdr->AceType), pAceHdr->AceFlags, pAceHdr->AceSize);
     540#endif
     541                            /* Note: We print the ACEs in canonoical order. */
     542                            switch (pAceHdr->AceType)
     543                            {
     544                                case ACCESS_ALLOWED_ACE_TYPE: /* We're only interested in the ALLOW ACE. */
     545                                {
     546                                    ACCESS_ALLOWED_ACE const *pAce = (ACCESS_ALLOWED_ACE *)pAceHdr;
     547                                    PSID const pSid                = (PSID)&pAce->SidStart;
     548#ifdef DEBUG
     549                                    char *pszSid = dbgSidToNameA(pSid);
     550                                    logStringF(hModule, "checkTargetDirOne:\t%s fMask=%#x", pszSid, pAce->Mask);
     551                                    RTStrFree(pszSid);
     552#endif
     553                                    /* We check the flags here first for performance reasons. */
     554                                    if ((pAce->Mask & pCtx->fAccessMaskForbidden) == pCtx->fAccessMaskForbidden)
     555                                    {
     556                                        for (size_t idxSID = 0; idxSID < pCtx->cWellKnownSidsForbidden; idxSID++)
     557                                        {
     558                                            PSID const pSidForbidden = pCtx->paWellKnownSidsForbidden[idxSID];
     559                                            bool const fForbidden    = EqualSid(pSid, pSidForbidden);
     560#ifdef DEBUG
     561                                            char *pszName = dbgSidToNameA(pSidForbidden);
     562                                            logStringF(hModule, "checkTargetDirOne:\t%s : %s",
     563                                                       fForbidden ? "** FORBIDDEN **" : "ALLOWED        ", pszName);
     564                                            RTStrFree(pszName);
     565#endif /* DEBUG */
     566                                            if (fForbidden)
     567                                            {
     568                                                vrc = VERR_INVALID_NAME;
     569                                                break;
     570                                            }
     571                                        }
     572                                    }
     573
     574                                    break;
     575                                }
     576
     577                                case ACCESS_DENIED_ACE_TYPE: /* We're only interested in the ALLOW ACE. */
     578                                {
     579                                    ACCESS_DENIED_ACE const *pAce = (ACCESS_DENIED_ACE *)pAceHdr;
     580#ifdef DEBUG
     581                                    LPWSTR pwszSid = NULL;
     582                                    ConvertSidToStringSid((PSID)&pAce->SidStart, &pwszSid);
     583
     584                                    logStringF(hModule, "checkTargetDirOne:\t%ls fMask=%#x (generic %#x specific %#x)",
     585                                               pwszSid ? pwszSid : L"<Allocation Error>", pAce->Mask);
     586#endif /* DEBUG */
     587                                    LocalFree(pwszSid);
     588
     589                                    /* Ignore everything else. */
     590                                    break;
     591                                }
     592                            }
     593                        }
     594                        else
     595                            dwErr = GetLastError();
     596
     597                        /* No point in checking further if we failed somewhere above. */
     598                        if (RT_FAILURE(vrc))
     599                            break;
     600
     601                    } /* for ACE */
     602                }
     603                else
     604                    dwErr = GetLastError();
     605            }
     606        }
     607        else
     608            dwErr = GetLastError();
     609
     610        LocalFree(pSecurityDescriptor);
     611    }
     612    else
     613        dwErr = GetLastError();
     614
     615    if (RT_SUCCESS(vrc))
     616        vrc = RTErrConvertFromWin32(dwErr);
     617
     618#ifdef DEBUG
     619    logStringF(hModule, "checkTargetDirOne: Returning %Rrc", vrc);
     620#endif
     621
     622    if (   RT_FAILURE(vrc)
     623        && vrc != VERR_INVALID_NAME)
     624        logStringF(hModule, "checkTargetDirOne: Failed with %Rrc (%#x)", vrc, dwErr);
     625
     626    return vrc;
     627}
     628
     629/**
     630 * Checks whether the path in the public property INSTALLDIR has the correct ACL permissions and returns whether
     631 * it's valid or not.
     632 *
     633 * Called from the MSI installer as a custom action.
     634 *
     635 * @returns Success status (acccording to MSI custom actions).
     636 * @retval  ERROR_SUCCESS if checking the target directory turned out to be valid.
     637 * @retval  ERROR_NO_NET_OR_BAD_PATH is the target directory is invalid.
     638 * @param   hModule             Windows installer module handle.
     639 *
     640 * @note    Sets private property VBox_Target_Dir_Is_Valid to "1" (true) if the given target path is valid,
     641 *          or "0" (false) if it is not. An empty target directory is considered to be valid (i.e. INSTALLDIR not set yet).
     642 *
     643 * @sa      @bugref{10616}
     644 */
     645UINT __stdcall CheckTargetDir(MSIHANDLE hModule)
     646{
     647    char *pszTargetDir;
     648
     649    int vrc = VBoxGetMsiPropUtf8(hModule, "INSTALLDIR", &pszTargetDir);
     650    if (RT_SUCCESS(vrc))
     651    {
     652        logStringF(hModule, "CheckTargetDir: Checking target directory '%s' ...", pszTargetDir);
     653
     654        if (!RTStrNLen(pszTargetDir, RTPATH_MAX))
     655        {
     656            logStringF(hModule, "CheckTargetDir: No INSTALLDIR set (yet), skipping ...");
     657            VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"1");
     658        }
     659        else
     660        {
     661            union
     662            {
     663                RTPATHPARSED    Parsed;
     664                uint8_t         ab[RTPATH_MAX];
     665            } u;
     666
     667            vrc = RTPathParse(pszTargetDir, &u.Parsed, sizeof(u), RTPATH_STR_F_STYLE_DOS);
     668            if (RT_SUCCESS(vrc))
     669            {
     670                if (u.Parsed.fProps & RTPATH_PROP_DOTDOT_REFS)
     671                    vrc = VERR_INVALID_PARAMETER;
     672                if (RT_SUCCESS(vrc))
     673                {
     674                    vrc = initTargetDirSecurityCtx(&g_TargetDirSecCtx, hModule, pszTargetDir);
     675                    if (RT_SUCCESS(vrc))
     676                    {
     677                        uint16_t idxComp = u.Parsed.cComps;
     678                        char     szPathToCheck[RTPATH_MAX];
     679                        while (idxComp > 1) /* We traverse backwards from INSTALLDIR and leave out the root (e.g. C:\"). */
     680                        {
     681                            u.Parsed.cComps = idxComp;
     682                            vrc = RTPathParsedReassemble(pszTargetDir, &u.Parsed, RTPATH_STR_F_STYLE_DOS,
     683                                                         szPathToCheck, sizeof(szPathToCheck));
     684                            if (RT_FAILURE(vrc))
     685                                break;
     686                            if (RTDirExists(szPathToCheck))
     687                            {
     688                                vrc = checkTargetDirOne(hModule, &g_TargetDirSecCtx, szPathToCheck);
     689                                if (RT_FAILURE(vrc))
     690                                    break;
     691                            }
     692                            else
     693                                logStringF(hModule, "CheckTargetDir: Path '%s' does not exist (yet)", szPathToCheck);
     694                            idxComp--;
     695                        }
     696
     697                        destroyTargetDirSecurityCtx(&g_TargetDirSecCtx);
     698                    }
     699                    else
     700                        logStringF(hModule, "CheckTargetDir: initTargetDirSecurityCtx failed with %Rrc\n", vrc);
     701
     702                    if (RT_SUCCESS(vrc))
     703                        VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"1");
     704                }
     705            }
     706            else
     707                logStringF(hModule, "CheckTargetDir: Parsing path failed with %Rrc", vrc);
     708        }
     709
     710        RTStrFree(pszTargetDir);
     711    }
     712
     713    if (RT_FAILURE(vrc)) /* On failure (or when in doubt), mark the installation directory as invalid. */
     714    {
     715        logStringF(hModule, "CheckTargetDir: Checking failed with %Rrc", vrc);
     716        VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"0");
     717    }
     718
     719    /* Return back outcome to the MSI engine. */
     720    return RT_SUCCESS(vrc) ? ERROR_SUCCESS : ERROR_NO_NET_OR_BAD_PATH;
    162721}
    163722
  • trunk/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def

    r98103 r104162  
    3030    IsSerialCheckNeeded
    3131    CheckSerial
     32    CheckTargetDir
    3233    IsMSCRTInstalled
    3334    IsPythonInstalled
     
    3940    InstallNetFlt
    4041    UninstallNetFlt
    41         UninstallNetAdp
    42         InstallNetLwf
     42    UninstallNetAdp
     43    InstallNetLwf
    4344    UninstallNetLwf
    4445    UninstallTAPInstances
  • trunk/src/VBox/Installer/win/NLS/de_DE.wxl

    r98103 r104162  
    6464    <String Id="VB_NetLwfDriver">[ProductName] Treiber für NDIS6-Netzwerkbrücke.</String>
    6565    <String Id="VB_NetAdp6Driver">[ProductName] Treiber für virtuellen Netzwerk-Adapter für NDIS6-Host-only-Netzwerke.</String>
    66 
    67   <String Id="VB_Python">Python-Support für VirtualBox.</String>
     66    <String Id="VB_Python">Python-Support für VirtualBox.</String>
    6867
    6968    <!---->
     
    7675    <String Id="SunFound">Eine alte Sun Version von VirtualBox wurde auf diesem Computer gefunden. Bitte deinstallieren Sie diese Version zuerst. Danach können Sie [ProductName] installieren!</String>
    7776    <String Id="InnotekFound">Eine alte innotek Version von VirtualBox wurde auf diesem Computer gefunden. Bitte deinstallieren Sie diese Version zuerst. Danach können Sie [ProductName] installieren!</String>
     77    <String Id="InvalidTargetDir">Ungültiges Installationsverzeichnis angegeben. Bitte ein anderes Installationsverzeichnis wählen, um [ProductName] zu installieren.</String>
    7878
    7979    <!---->
     
    9292    <String Id="LicenseAgreementDlg_Accept">Ich &amp;akzeptiere die Bedingungen des Lizenzvertrags.</String>
    9393    <String Id="LicenseAgreementDlg_Decline">Ich &amp;akzeptiere die Bedingungen des Lizenzvertrags nicht.</String>
     94
     95    <!---->
     96    <String Id="InvalidTargetDirDlg_Header">Ungültiges Installationsverzeichnis</String>
     97    <String Id="InvalidTargetDirDlg_Desc1">Das gewählte Installationsverzeichnis is ungültig, da dieses nicht den Sicherheitsrichtlinien entspricht.</String>
     98    <String Id="InvalidTargetDirDlg_Desc2">Bitte ein anderes Installationsverzeichnis wählen um [ProductName] zu installieren.</String>
    9499
    95100    <!---->
  • trunk/src/VBox/Installer/win/NLS/el_GR.wxl

    r98103 r104162  
    6464    <String Id="VB_NetLwfDriver">Οδηγός [ProductName] για NDIS6 γεφυρωμένα δίκτυα.</String>
    6565    <String Id="VB_NetAdp6Driver">Οδηγός [ProductName] εικονικής κάρτας δικτύου για NDIS6 μόνο-με-οικοδεσπότη δίκτυα.</String>
    66 
    6766    <String Id="VB_Python">Υποστήριξη Python για το VirtualBox.</String>
    6867
     
    7675    <String Id="SunFound">Βρέθηκε μία παλιότερη εγκατάσταση του Sun VirtualBox στον υπολογιστή. Καταργήστε πρώτα την εγκατάσταση αυτού του πακέτου και μετά εγκαταστήστε το [ProductName]!</String>
    7776    <String Id="InnotekFound">Βρέθηκε μία παλιότερη εγκατάσταση του innotek VirtualBox στον υπολογιστή. Καταργήστε πρώτα την εγκατάσταση αυτού του πακέτου και μετά εγκαταστήστε το [ProductName]!</String>
     77    <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7878
    7979    <!---->
     
    9292    <String Id="LicenseAgreementDlg_Accept">Αποδέχομαι τους όρους της Άδειας Χρήσης</String>
    9393    <String Id="LicenseAgreementDlg_Decline">Δεν αποδέχομαι τους όρους της Άδειας Χρήσης</String>
     94
     95    <!---->
     96
     97    <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     98    <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     99    <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    94100
    95101    <!---->
  • trunk/src/VBox/Installer/win/NLS/en_US.wxl

    r98103 r104162  
    6464    <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String>
    6565    <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String>
    66 
    6766    <String Id="VB_Python">Python support for VirtualBox.</String>
    6867
     
    7675    <String Id="SunFound">An old Sun VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]!</String>
    7776    <String Id="InnotekFound">An old innotek VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]!</String>
     77    <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7878
    7979    <!---->
     
    9292    <String Id="LicenseAgreementDlg_Accept">I &amp;accept the terms in the License Agreement</String>
    9393    <String Id="LicenseAgreementDlg_Decline">I &amp;do not accept the terms in the License Agreement</String>
     94
     95    <!---->
     96
     97    <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     98    <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     99    <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    94100
    95101    <!---->
  • trunk/src/VBox/Installer/win/NLS/fa_IR.wxl

    r98103 r104162  
    5959    <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String>
    6060    <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String>
    61 
    62   <String Id="VB_Python">پشتیبانی از پایتون برای ویرچوال باکس.</String>
     61    <String Id="VB_Python">پشتیبانی از پایتون برای ویرچوال باکس.</String>
    6362    <!---->
    6463    <String Id="NeedAdmin">برای حذف [ProductName] شما نیاز به اجازه مدیر دارید! این راه انداز حالا لغو میشود.</String>
     
    6968    <String Id="SunFound">یک نصب قدیمی ویرچوال باکس روی این رایانه یافت شد. لطفا اول این بسته را حذف سپس [ProductName] را نصب کنید!</String>
    7069    <String Id="InnotekFound">یک نسخه قدیمی نصب ویرچوال باکس در این ماشین یافت شد. لطفا اول این بسته را حذف و سپس [ProductName] را نصب کنید!</String>
     70    <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7171    <!---->
    7272    <String Id="CancelDlg_Question">آیا میخواهید نصب [ProductName] را لغو کنید؟</String>
     
    7979    <String Id="LicenseAgreementDlg_Accept">&amp;من ضوابط را در توافقنامه مجوز می پذیرم</String>
    8080    <String Id="LicenseAgreementDlg_Decline">&amp;من ضوابط را در توافقنامه مجوز نمی پذیرم</String>
     81    <!---->
     82    <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     83    <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     84    <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    8185    <!---->
    8286    <String Id="CheckSerialDlg_Header">شماره سریال</String>
  • trunk/src/VBox/Installer/win/NLS/fr_FR.wxl

    r98103 r104162  
    6464    <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String>
    6565    <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String>
    66 
    67   <String Id="VB_Python">Python support for VirtualBox.</String>
     66    <String Id="VB_Python">Python support for VirtualBox.</String>
    6867
    6968    <!---->
     
    7574    <String Id="Only64Bit">Cette application ne marche que sur des systèmes Windows 64-bit. Veuillez installer la version 32-bit de [ProductName]!</String>
    7675    <String Id="InnotekFound">Vous avez une ancienne installation de innotek VirtualBox sur cette machine. Il vous faudra la désinstaller avant de pouvoir installer [ProductName].</String>
     76    <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7777
    7878    <!---->
     
    9191    <String Id="LicenseAgreementDlg_Accept">J'&amp;accepte les termes du Contrat de licence</String>
    9292    <String Id="LicenseAgreementDlg_Decline">Je &amp;n'accepte pas les termes du Contrat de licence</String>
     93
     94    <!---->
     95
     96    <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     97    <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     98    <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    9399
    94100    <!---->
  • trunk/src/VBox/Installer/win/NLS/it_IT.wxl

    r98103 r104162  
    5959    <String Id="VB_NetLwfDriver">Driver di [ProductName] per la rete con bridge NDIS6.</String>
    6060    <String Id="VB_NetAdp6Driver">Driver di [ProductName] per la scheda di rete virtuale per la rete solo host NDIS6.</String>
    61 
    62   <String Id="VB_Python">Supporto Python per VirtualBox.</String>
     61    <String Id="VB_Python">Supporto Python per VirtualBox.</String>
    6362    <!---->
    6463    <String Id="NeedAdmin">Devi avere diritti di amministrazione per (dis)installare [ProductName]! L'installazione sarà interrotta immediatamente.</String>
     
    6968    <String Id="SunFound">Una vecchia installazione di Sun VirtualBox è stata trovata su questa macchina. Disinstalla prima questo pacchetto e poi installa [ProductName]!</String>
    7069    <String Id="InnotekFound">Una vecchia installazione di innotek VirtualBox è stata trovata su questa macchina. Disinstalla prima questo pacchetto e poi installa [ProductName]!</String>
     70    <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7171    <!---->
    7272    <String Id="CancelDlg_Question">Sei sicuro di voler annullare l'installazione di [ProductName]?</String>
     
    7979    <String Id="LicenseAgreementDlg_Accept">&amp;Accetto i termini dell'accordo di licenza</String>
    8080    <String Id="LicenseAgreementDlg_Decline">&amp;Non accetto i termini dell'accordo di licenza</String>
     81    <!---->
     82    <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     83    <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     84    <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    8185    <!---->
    8286    <String Id="CheckSerialDlg_Header">Numero di serie</String>
  • trunk/src/VBox/Installer/win/NLS/ru_RU.wxl

    r98103 r104162  
    6464    <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String>
    6565    <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String>
    66 
    6766    <String Id="VB_Python">Python support for VirtualBox.</String>
    6867
     
    7675    <String Id="SunFound">An old Sun VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]!</String>
    7776    <String Id="InnotekFound">An old innotek VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]!</String>
     77    <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7878
    7979    <!---->
     
    9292    <String Id="LicenseAgreementDlg_Accept">I &amp;accept the terms in the License Agreement</String>
    9393    <String Id="LicenseAgreementDlg_Decline">I &amp;do not accept the terms in the License Agreement</String>
     94
     95    <!---->
     96
     97    <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     98    <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     99    <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    94100
    95101    <!---->
  • trunk/src/VBox/Installer/win/NLS/tr_TR.wxl

    r99363 r104162  
    6464    <String Id="VB_NetLwfDriver">NDIS6 Köprü Ağı Oluşturma için [ProductName] sürücüsü.</String>
    6565    <String Id="VB_NetAdp6Driver">NDIS6 Yalnızca-Anamakine Ağı Oluşturma için [ProductName] sanal ağ bağdaştırıcısı sürücüsü.</String>
    66 
    67   <String Id="VB_Python">VirtualBox için Python desteği.</String>
     66    <String Id="VB_Python">VirtualBox için Python desteği.</String>
    6867
    6968    <!---->
     
    7675    <String Id="SunFound">Bu makinede eski bir Sun VirtualBox kurulumu bulundu. Lütfen önce bu paketi kaldırın ve sonra [ProductName] yükleyin!</String>
    7776    <String Id="InnotekFound">Bu makinede eski bir innotek VirtualBox kurulumu bulundu. Lütfen önce bu paketi kaldırın ve sonra [ProductName] yükleyin!</String>
     77    <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7878
    7979    <!---->
     
    9292    <String Id="LicenseAgreementDlg_Accept">Lisans Sözleşmesi içindeki şartları kabul e&amp;diyorum</String>
    9393    <String Id="LicenseAgreementDlg_Decline">Lisans Sözleşmesi içindeki şartları kabul e&amp;tmiyorum</String>
     94
     95    <!---->
     96
     97    <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     98    <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     99    <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    94100
    95101    <!---->
  • trunk/src/VBox/Installer/win/NLS/zh_CN.wxl

    r98103 r104162  
    6464<String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String>
    6565<String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String>
    66 
    6766<String Id="VB_Python">VirtualBox 的 Python 支持。</String>
    6867
     
    7675<String Id="SunFound">在此计算机发现旧的 Sun VirtualBox 安装。 请先卸载此组件然后安装 [ProductName]!</String>
    7776<String Id="InnotekFound">在此计算机发现旧的 innotek VirtualBox 安装。 请先卸载此组件然后安装 [ProductName]!</String>
     77<String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7878
    7979<!---->
     
    9292<String Id="LicenseAgreementDlg_Accept">我接受授权协议中条款(&amp;A)</String>
    9393<String Id="LicenseAgreementDlg_Decline">我不接受授权协议中条款(&amp;D)</String>
     94
     95<!---->
     96
     97<String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     98<String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     99<String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    94100
    95101<!---->
  • trunk/src/VBox/Installer/win/NLS/zh_TW.wxl

    r99363 r104162  
    6464    <String Id="VB_NetLwfDriver">[ProductName] 驅動程式針對 NDIS6 橋接網路。</String>
    6565    <String Id="VB_NetAdp6Driver">[ProductName] 虛擬網路介面卡針對 NDIS6 「僅限主機」網路。</String>
    66 
    6766    <String Id="VB_Python">VirtualBox 的 Python 支援。</String>
    6867
     
    7675    <String Id="SunFound">在此電腦發現舊的 Sun VirtualBox 安裝。 請先解除安裝此套件然後安裝 [ProductName]!</String>
    7776    <String Id="InnotekFound">在此電腦發現舊的 innotek VirtualBox 安裝。 請先解除安裝此套件然後安裝 [ProductName]!</String>
     77    <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String>
    7878
    7979    <!---->
     
    9292    <String Id="LicenseAgreementDlg_Accept">我接受授權協議中條款(&amp;A)</String>
    9393    <String Id="LicenseAgreementDlg_Decline">我不接受授權協議中條款(&amp;D)</String>
     94
     95    <!---->
     96
     97    <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String>
     98    <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String>
     99    <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String>
    94100
    95101    <!---->
  • trunk/src/VBox/Installer/win/UserInterface.wxi

    r98103 r104162  
    207207        </Dialog>
    208208
     209        <!-- Shows a dialog which tells the user that the chosen installation directory is invalid and therefore cannot be used. -->
     210        <Dialog Id="VBoxInvalidTargetDirDlg" Width="370" Height="270" Title="[ProductName] !(loc.Setup)" NoMinimize="yes">
     211
     212            <!-- The wizard has a bitmap as background. The source is defined as a property below. -->
     213            <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
     214
     215            <!-- Title text drawn on the background -->
     216            <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
     217                <Text>{\DlgInvalidSerial}!(loc.InvalidTargetDirDlg_Header)</Text>
     218            </Control>
     219
     220            <!-- Text saying what we gonna do -->
     221            <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="130" Transparent="yes" NoPrefix="yes">
     222                <Text>!(loc.InvalidTargetDirDlg_Desc1)</Text>
     223            </Control>
     224
     225            <Control Id="Description2" Type="Text" X="135" Y="95" Width="220" Height="130" Transparent="yes" NoPrefix="yes">
     226                <Text>!(loc.InvalidTargetDirDlg_Desc2)</Text>
     227            </Control>
     228
     229            <!-- And a line for looking nice... -->
     230            <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
     231
     232            <!-- Build number text drawn left bottom -->
     233            <Control Id="Build" Type="Text" X="20" Y="247" Width="220" Height="10" Transparent="yes" NoPrefix="yes">
     234                <Text>[Version_text] $(var.Property_Version)</Text>
     235            </Control>
     236
     237            <Control Id="Back" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.ButtonText_Back)"/>
     238
     239            <!-- Canceling will bring up a confirmation dialog ('SpawnDialog' attribute) -->
     240            <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.ButtonText_Cancel)">
     241                <Publish Event="SpawnDialog" Value="VBoxCancelDlg">1</Publish>
     242            </Control>
     243
     244        </Dialog>
     245
    209246        <!-- Dialog used to set another installation path. This is taken from the tutorial template on the web and can also be
    210247             used for package selection etc. if necessary after some tweaking. -->
     
    221258                <Text>!(loc.CustomizeDlg_IconTree)</Text>
    222259            </Control>
    223             <Control Id="Tree" Type="SelectionTree" X="25" Y="85" Width="175" Height="95" Property="_BrowseProperty"
     260            <Control Id="Tree" Type="SelectionTree" X="25" Y="85" Width="175" Height="95" Property="VBOX_TARGET_DIR"
    224261                     Sunken="yes" TabSkip="no" Text="Tree of selections" />
    225262            <Control Id="Browse" Type="PushButton" X="304" Y="200" Width="56" Height="17" Text="!(loc.ButtonText_Browse)">
     
    466503        <!-- Dialog used to change the installation directory -->
    467504        <Dialog Id="VBoxBrowseDlg" Width="370" Height="270" Title="[ProductName] !(loc.Setup)" NoMinimize="yes">
    468             <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="18" Property="_BrowseProperty" Indirect="yes" />
    469             <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.ButtonText_OK)">
    470                 <Publish Event="SetTargetPath" Value="[_BrowseProperty]">1</Publish>
    471                 <Publish Event="EndDialog" Value="Return">1</Publish>
    472             </Control>
    473             <Control Id="Cancel" Type="PushButton" X="240" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.ButtonText_Cancel)">
    474                 <Publish Event="Reset" Value="0">1</Publish>
    475                 <Publish Event="EndDialog" Value="Return">1</Publish>
    476             </Control>
     505            <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="18" Property="VBOX_TARGET_DIR" Indirect="yes" />
     506            <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.ButtonText_OK)" />
     507            <Control Id="Cancel" Type="PushButton" X="240" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.ButtonText_Cancel)"/>
    477508            <Control Id="ComboLabel" Type="Text" X="25" Y="58" Width="44" Height="10" TabSkip="no" Text="!(loc.BrowseDlg_LookIn)" />
    478509            <Control Id="DirectoryCombo" Type="DirectoryCombo" X="70" Y="55" Width="220" Height="80"
    479                      Property="_BrowseProperty" Indirect="yes" Fixed="yes" Remote="yes">
     510                     Property="VBOX_TARGET_DIR" Indirect="yes" Fixed="yes" Remote="yes">
    480511                <Subscribe Event="IgnoreChange" Attribute="IgnoreChange" />
    481512            </Control>
     
    488519            </Control>
    489520            <Control Id="DirectoryList" Type="DirectoryList" X="25" Y="83" Width="320" Height="110"
    490                      Property="_BrowseProperty" Sunken="yes" Indirect="yes" TabSkip="no" />
     521                     Property="VBOX_TARGET_DIR" Sunken="yes" Indirect="yes" TabSkip="no" />
    491522            <Control Id="PathLabel" Type="Text" X="25" Y="205" Width="59" Height="10" TabSkip="no" Text="!(loc.BrowseDlg_FolderName)" />
    492523            <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
     
    11781209        <Publish Dialog="VBoxWrongSerialDlg" Control="Back" Event="NewDialog" Value="VBoxCheckSerialDlg">1</Publish>
    11791210
    1180         <!-- Note: We have to set (1) or unset ({}) the properties first (see order #), as those will be needed for further routing. -->
    1181         <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_PYTHONAPI_DLG" Value="1" Order="1"><![CDATA[(&VBoxPython=3) AND (VBOX_PYTHON_DEPS_INSTALLED="0")]]></Publish>
    1182         <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_PYTHONAPI_DLG" Value="{}" Order="2"><![CDATA[(&VBoxPython<3)]]></Publish>
    1183         <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_DISCONNECTIFACES_DLG" Value="1" Order="3"><![CDATA[&VBoxNetworkFlt=3]]></Publish>
    1184         <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_DISCONNECTIFACES_DLG" Value="{}" Order="4"><![CDATA[&VBoxNetworkFlt<3]]></Publish>
    1185         <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxWarnDisconNetIfacesDlg" Order="10"><![CDATA[VBOX_SHOW_WARN_DISCONNECTIFACES_DLG]]></Publish>
    1186         <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxWarnPythonDlg" Order="11"><![CDATA[VBOX_SHOW_WARN_PYTHONAPI_DLG AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG)]]></Publish>
    1187         <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxCustomize2Dlg" Order="12"><![CDATA[VBOX_SHOW_CUSTOMIZE2_DLG AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_WARN_PYTHONAPI_DLG)]]></Publish>
    1188         <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxVerifyReadyDlg" Order="13"><![CDATA[(NOT VBOX_SHOW_CUSTOMIZE2_DLG) AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_WARN_PYTHONAPI_DLG)]]></Publish>
     1211        <Publish Dialog="VBoxBrowseDlg" Control="OK" Event="SetTargetPath" Value="[VBOX_TARGET_DIR]" Order="1">1</Publish>
     1212        <Publish Dialog="VBoxBrowseDlg" Control="OK" Event="EndDialog" Value="Return" Order="2">1</Publish>
     1213        <Publish Dialog="VBoxBrowseDlg" Control="Cancel" Event="Reset" Value="0" Order="1">1</Publish>
     1214        <Publish Dialog="VBoxBrowseDlg" Control="Cancel" Event="EndDialog" Value="Return" Order="2">1</Publish>
     1215
     1216        <Publish Dialog="VBoxInvalidTargetDirDlg" Control="Back" Event="NewDialog" Value="VBoxCustomizeDlg">1</Publish>
     1217
     1218        <!-- Note:  We have to set (1) or unset ({}) the properties first (see order #), as those will be needed for further routing.
     1219             Note2: I'd love to make this easier to read/follow, but this is how Windows Installer XML works for processing all these events, sigh. -->
     1220
     1221        <!-- Check if the chosen installation directory turned out to be invalid by calling our installation helper DLL
     1222             and performing a custom action. See @bugref{10616} -->
     1223        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="DoAction" Value="ca_CheckTargetDirPre" Order="1">1</Publish>
     1224        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_INVALID_TARGET_DLG" Value="1" Order="2"><![CDATA[VBox_Target_Dir_Is_Valid="0"]]></Publish>
     1225        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_PYTHONAPI_DLG" Value="1" Order="3"><![CDATA[(&VBoxPython=3) AND (VBOX_PYTHON_DEPS_INSTALLED="0")]]></Publish>
     1226        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_PYTHONAPI_DLG" Value="{}" Order="4"><![CDATA[(&VBoxPython<3)]]></Publish>
     1227        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_DISCONNECTIFACES_DLG" Value="1" Order="5"><![CDATA[&VBoxNetworkFlt=3]]></Publish>
     1228        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_DISCONNECTIFACES_DLG" Value="{}" Order="6"><![CDATA[&VBoxNetworkFlt<3]]></Publish>
     1229        <!-- Show an error dialog if the chosen installation directory was found to be invalid. See @bugref{10616} -->
     1230        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxInvalidTargetDirDlg" Order="10">1</Publish>
     1231        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxWarnDisconNetIfacesDlg" Order="11"><![CDATA[VBOX_SHOW_WARN_DISCONNECTIFACES_DLG]]></Publish>
     1232        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxWarnPythonDlg" Order="12"><![CDATA[VBOX_SHOW_WARN_PYTHONAPI_DLG AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG)]]></Publish>
     1233        <!-- Only allow going to the next stage if the chosen installation directory is valid. See @bugref{10616} -->
     1234        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxCustomize2Dlg" Order="13"><![CDATA[VBOX_SHOW_CUSTOMIZE2_DLG AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_WARN_PYTHONAPI_DLG) AND (NOT VBox_Target_Dir_Is_Valid="0")]]></Publish>
     1235        <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxVerifyReadyDlg" Order="14"><![CDATA[(NOT VBOX_SHOW_CUSTOMIZE2_DLG) AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_WARN_PYTHONAPI_DLG)]]></Publish>
    11891236        <Publish Dialog="VBoxCustomizeDlg" Control="Back" Event="NewDialog" Value="VBoxCheckSerialDlg"><![CDATA[VBOX_SHOW_SERIAL_CHECK_DLG]]></Publish>
    11901237        <Publish Dialog="VBoxCustomizeDlg" Control="Back" Event="NewDialog" Value="VBoxLicenseAgreementDlg"><![CDATA[NOT VBOX_SHOW_SERIAL_CHECK_DLG]]></Publish>
     
    12121259            <Custom Action="ca_IsMSCRTInstalled" After="AppSearch" />
    12131260<?endif?>
     1261            <Custom Action="ca_CheckTargetDirPre" After="AppSearch"/> <!-- Required for launch conditions. See @bugref{10616} -->
    12141262            <Custom Action="ca_OriginalTargetDir" After="FileCost"><![CDATA[(NOT INSTALLDIR) AND (NOT EXISTINGINSTALLDIR)]]></Custom>
    12151263            <Custom Action="ca_DefaultTargetDir" After="FileCost"><![CDATA[NOT Installed AND (NOT INSTALLDIR) AND EXISTINGINSTALLDIR]]></Custom>
  • trunk/src/VBox/Installer/win/VBoxMergeApp.wxi

    r103369 r104162  
    128128                    Vital="yes">
    129129            <ServiceDependency Id="RPCSS" />
     130            <ServiceConfig ServiceSid="restricted" OnInstall="yes" OnReinstall="yes" />
    130131        </ServiceInstall>
    131132        <ServiceControl Id="VBoxSDSControl" Name="VBoxSDS" Stop="both" Remove="uninstall" />
  • trunk/src/VBox/Installer/win/VBoxMergeAppCA.wxi

    r98103 r104162  
    3636                  DllEntry="IsWindows10" Execute="immediate" Return="ignore" Impersonate="no" />
    3737
     38    <!-- Makes sure we check if the chosen target directory is valid before allowing to install. See @bugref{10616} -->
     39    <CustomAction Id="ca_CheckTargetDirPre" BinaryKey="VBoxInstallHelper"
     40                  DllEntry="CheckTargetDir" Execute="immediate" Return="ignore" Impersonate="no" />
     41    <!-- Makes sure that the target directory we installed into still is valid. Rollback if it isn't. See @bugref{10616} -->
     42    <CustomAction Id="ca_CheckTargetDirPost" BinaryKey="VBoxInstallHelper"
     43                  DllEntry="CheckTargetDir" Execute="immediate" Return="check" Impersonate="no" />
    3844</Include>
    3945
  • trunk/src/VBox/Installer/win/VBoxMergeAppSeq.wxi

    r98103 r104162  
    3131    <Custom Action="ca_IsMSCRTInstalled" After="AppSearch">1</Custom>
    3232<?endif?>
     33    <!-- Required for lauch conditions. See @bugref{10616} -->
     34    <Custom Action="ca_CheckTargetDirPre" After="AppSearch"/>
     35    <!-- Check if the installation directory still fits our security requirements after we finalized installation.
     36         See @bugref{10616} -->
     37    <Custom Action="ca_CheckTargetDirPost" After="InstallFinalize"><![CDATA[NOT REMOVE]]></Custom>
    3338
    3439    <Custom Action="ca_IsWindows10" After="FileCost">1</Custom>
  • trunk/src/VBox/Installer/win/VirtualBox.wxs

    r103038 r104162  
    128128    </Condition>
    129129<?endif ?>
     130    <!-- Check if the current INSTALLDIR is valid or not, or if VBox already is installed.
     131         Thight might be handed-in via command line (MSI properties) or through a customized merge module. See @bugref{10616} -->
     132    <Condition Message="!(loc.InvalidTargetDir)">
     133        Installed OR (VBox_Target_Dir_Is_Valid="1")
     134    </Condition>
    130135
    131136    <!-- Detect old innotek installation -->
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