From cd47c2446f1a9dee96610f298989848f8986a8be Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 00:55:52 +0200 Subject: Merging upstream version 7.0.16-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/Installer/darwin/Makefile.kmk | 6 + src/VBox/Installer/linux/VBox.sh | 30 +- src/VBox/Installer/linux/install.sh | 15 +- src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec | 7 +- src/VBox/Installer/linux/vboxdrv.sh | 6 +- src/VBox/Installer/win/InstallHelper/Makefile.kmk | 20 +- .../Installer/win/InstallHelper/VBoxCommon.cpp | 38 +- .../win/InstallHelper/VBoxInstallHelper.cpp | 763 +++++++++++++++++++-- .../win/InstallHelper/VBoxInstallHelper.def | 5 +- src/VBox/Installer/win/NLS/de_DE.wxl | 9 +- src/VBox/Installer/win/NLS/el_GR.wxl | 8 +- src/VBox/Installer/win/NLS/en_US.wxl | 8 +- src/VBox/Installer/win/NLS/fa_IR.wxl | 8 +- src/VBox/Installer/win/NLS/fr_FR.wxl | 10 +- src/VBox/Installer/win/NLS/it_IT.wxl | 8 +- src/VBox/Installer/win/NLS/ru_RU.wxl | 8 +- src/VBox/Installer/win/NLS/tr_TR.wxl | 10 +- src/VBox/Installer/win/NLS/zh_CN.wxl | 8 +- src/VBox/Installer/win/NLS/zh_TW.wxl | 8 +- src/VBox/Installer/win/UserInterface.wxi | 92 ++- src/VBox/Installer/win/VBoxMergeAppCA.wxi | 6 + src/VBox/Installer/win/VBoxMergeAppSeq.wxi | 5 + src/VBox/Installer/win/VirtualBox.wxs | 5 + 23 files changed, 917 insertions(+), 166 deletions(-) (limited to 'src/VBox/Installer') diff --git a/src/VBox/Installer/darwin/Makefile.kmk b/src/VBox/Installer/darwin/Makefile.kmk index 494fd990..1b7a16f8 100644 --- a/src/VBox/Installer/darwin/Makefile.kmk +++ b/src/VBox/Installer/darwin/Makefile.kmk @@ -483,6 +483,12 @@ if defined(VBOX_WITH_PYTHON) && !defined(VBOX_WITHOUT_VBOXPYTHON_FOR_OSX_10_7) VBOX_DI_VBAPP_DYLIBS += \ MacOS/VBoxPython2_7.so endif +if defined(VBOX_WITH_PYTHON) \ + && !defined(VBOX_WITHOUT_PYTHON_LIMITED_API) \ + && exists "$(VBOX_PATH_DIST)/VirtualBox.app/Contents/MacOS/VBoxPython3.so" + VBOX_DI_VBAPP_DYLIBS += \ + MacOS/VBoxPython3.so +endif ifdef VBOX_WITH_VMSVGA3D VBOX_DI_VBAPP_DYLIBS += \ MacOS/VBoxSVGA3D.dylib \ diff --git a/src/VBox/Installer/linux/VBox.sh b/src/VBox/Installer/linux/VBox.sh index fb584d48..31e32f91 100755 --- a/src/VBox/Installer/linux/VBox.sh +++ b/src/VBox/Installer/linux/VBox.sh @@ -96,15 +96,33 @@ WARNING: The compilation of the vboxdrv.ko kernel module failed during the EOF fi -SERVER_PID=`ps -U \`whoami\` | grep VBoxSVC | awk '{ print $1 }'` +# Get effective user name to use it in order to compose XPCOM IPC socket path. +VBOX_EFFECTIVE_USER="$(whoami)" +if [ -z "$VBOX_EFFECTIVE_USER" ]; then + cat << EOF +WARNING: Unable to detect effective user name. VirtualBox might run incorrectly. +EOF +fi + +# Variables LOGNAME and USER are used by XPCOM code in order to +# compose IPC socket path. If they set to something which is different +# from the effective user name, it might result in misbehavior. +# Setting VBOX_IPC_SOCKETID will tell XPCOM code which path it should use explicitly. +[ -n "$LOGNAME" ] && [ "$LOGNAME" = "$VBOX_EFFECTIVE_USER" ] || vbox_override_env="1" +[ -n "$USER" ] && [ "$USER" = "$VBOX_EFFECTIVE_USER" ] || vbox_override_env="1" + +if [ -n "$vbox_override_env" ]; then +cat << EOF +WARNING: Environment variable LOGNAME or USER does not correspond to effective user id. +EOF + export VBOX_IPC_SOCKETID="$VBOX_EFFECTIVE_USER" +fi + +SERVER_PID=`ps -U "$VBOX_EFFECTIVE_USER" | grep VBoxSVC | awk '{ print $1 }'` if [ -z "$SERVER_PID" ]; then # Server not running yet/anymore, cleanup socket path. # See IPC_GetDefaultSocketPath()! - if [ -n "$LOGNAME" ]; then - rm -rf /tmp/.vbox-$LOGNAME-ipc > /dev/null 2>&1 - else - rm -rf /tmp/.vbox-$USER-ipc > /dev/null 2>&1 - fi + rm -rf "/tmp/.vbox-$VBOX_EFFECTIVE_USER-ipc" > /dev/null 2>&1 fi if [ "$SHUTDOWN" = "true" ]; then diff --git a/src/VBox/Installer/linux/install.sh b/src/VBox/Installer/linux/install.sh index 9c11eb9b..d32d9270 100755 --- a/src/VBox/Installer/linux/install.sh +++ b/src/VBox/Installer/linux/install.sh @@ -289,11 +289,8 @@ if [ "$ACTION" = "install" ]; then # create symlinks for working around unsupported $ORIGIN/.. in VBoxC.so (setuid), # and finally make sure the directory is only writable by the user (paranoid). if [ -n "$HARDENED" ]; then - if [ -f $INSTALLATION_DIR/VirtualBoxVM ]; then - test -e $INSTALLATION_DIR/VirtualBoxVM && chmod 4511 $INSTALLATION_DIR/VirtualBoxVM - else - test -e $INSTALLATION_DIR/VirtualBox && chmod 4511 $INSTALLATION_DIR/VirtualBox - fi + # Note! Update vboxdrv.sh if the VirtualBoxVM entry changes (bugref:10642). + test -e $INSTALLATION_DIR/VirtualBoxVM && chmod 4511 $INSTALLATION_DIR/VirtualBoxVM test -e $INSTALLATION_DIR/VBoxSDL && chmod 4511 $INSTALLATION_DIR/VBoxSDL test -e $INSTALLATION_DIR/VBoxHeadless && chmod 4511 $INSTALLATION_DIR/VBoxHeadless test -e $INSTALLATION_DIR/VBoxNetDHCP && chmod 4511 $INSTALLATION_DIR/VBoxNetDHCP @@ -325,9 +322,7 @@ if [ "$ACTION" = "install" ]; then # Create symlinks to start binaries ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VirtualBox - if [ -f $INSTALLATION_DIR/VirtualBoxVM ]; then - ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VirtualBoxVM - fi + ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VirtualBoxVM ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VBoxManage ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VBoxSDL ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VBoxVRDP @@ -362,9 +357,7 @@ if [ "$ACTION" = "install" ]; then # Convenience symlinks. The creation fails if the FS is not case sensitive ln -sf VirtualBox /usr/bin/virtualbox > /dev/null 2>&1 - if [ -f $INSTALLATION_DIR/VirtualBoxVM ]; then - ln -sf VirtualBoxVM /usr/bin/virtualboxvm > /dev/null 2>&1 - fi + ln -sf VirtualBoxVM /usr/bin/virtualboxvm > /dev/null 2>&1 ln -sf VBoxManage /usr/bin/vboxmanage > /dev/null 2>&1 ln -sf VBoxSDL /usr/bin/vboxsdl > /dev/null 2>&1 ln -sf VBoxHeadless /usr/bin/vboxheadless > /dev/null 2>&1 diff --git a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec index 829322aa..bab95a70 100644 --- a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec +++ b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec @@ -223,13 +223,8 @@ if [ -f $RPM_BUILD_ROOT/usr/lib/virtualbox/libQt5CoreVBox.so.5 ]; then fi rm -f $RPM_BUILD_ROOT/usr/lib/virtualbox/chrpath ln -s ../VBoxVMM.so $RPM_BUILD_ROOT/usr/lib/virtualbox/components/VBoxVMM.so -for i in VBoxHeadless VBoxNetDHCP VBoxNetNAT VBoxNetAdpCtl; do +for i in VirtualBoxVM VBoxHeadless VBoxNetDHCP VBoxNetNAT VBoxNetAdpCtl; do chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/$i; done -if test -e $RPM_BUILD_ROOT/usr/lib/virtualbox/VirtualBoxVM; then - chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/VirtualBoxVM -else - chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/VirtualBox -fi if [ -f $RPM_BUILD_ROOT/usr/lib/virtualbox/VBoxVolInfo ]; then chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/VBoxVolInfo fi diff --git a/src/VBox/Installer/linux/vboxdrv.sh b/src/VBox/Installer/linux/vboxdrv.sh index 4077c169..5e6842cf 100755 --- a/src/VBox/Installer/linux/vboxdrv.sh +++ b/src/VBox/Installer/linux/vboxdrv.sh @@ -85,10 +85,12 @@ else # Applies to Debian packages only (but shouldn't hurt elsewhere) exit 0 fi -VIRTUALBOX="${INSTALL_DIR}/VirtualBox" VBOXMANAGE="${INSTALL_DIR}/VBoxManage" BUILDINTMP="${MODULE_SRC}/build_in_tmp" -if test -u "${VIRTUALBOX}"; then + +# If the VirtualBoxVM file has the set-uid bit set or if it doesn't exist, setup vboxdrv +# in hardened mode. Otherwise, do the developer mode using vboxusers for access control. +if test -u "${INSTALL_DIR}/VirtualBoxVM" || test '!' -e "${INSTALL_DIR}/VirtualBoxVM"; then GROUP=root DEVICE_MODE=0600 else diff --git a/src/VBox/Installer/win/InstallHelper/Makefile.kmk b/src/VBox/Installer/win/InstallHelper/Makefile.kmk index cad3c4c3..38525a7d 100644 --- a/src/VBox/Installer/win/InstallHelper/Makefile.kmk +++ b/src/VBox/Installer/win/InstallHelper/Makefile.kmk @@ -33,9 +33,16 @@ DLLS += VBoxInstallHelper VBoxInstallHelper_TEMPLATE = VBoxR3StaticDllNoAsan VBoxInstallHelper_SDKS = ReorderCompilerIncs $(VBOX_WINPSDK) $(VBOX_WINDDK) VBoxInstallHelper_DEFS = _WIN32_WINNT=0x0501 _UNICODE UNICODE VBOX_SVN_REV=$(VBOX_SVN_REV) -ifdef VBOX_WITH_NETFLT +if defined(VBOX_WITH_NETFLT) || defined(VBOX_WITH_NETADP) VBoxInstallHelper_SDKS += VBoxWinNewDevLib - VBoxInstallHelper_DEFS += VBOX_WITH_NETFLT=1 + VBoxInstallHelper_DEFS += \ + $(if $(VBOX_WITH_NETFLT),VBOX_WITH_NETFLT,) \ + $(if $(VBOX_WITH_NETADP),VBOX_WITH_NETADP,) + VBoxInstallHelper_LIBS += \ + $(PATH_STAGE_LIB)/WinNetConfigSharedStatic.lib \ + $(PATH_STAGE_LIB)/VBoxDrvCfgSharedStatic.lib \ + $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \ + $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/WbemUuid.Lib endif VBoxInstallHelper_DEPS = $(VBOX_SVN_REV_KMK) VBoxInstallHelper_SOURCES = \ @@ -47,15 +54,8 @@ ifndef VBOX_OSE VBoxInstallHelper_SOURCES += \ internal/VBoxSerial.cpp endif -VBoxInstallHelper_LIBS = \ +VBoxInstallHelper_LIBS += \ $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/Msi.lib -ifdef VBOX_WITH_NETFLT - VBoxInstallHelper_LIBS += \ - $(PATH_STAGE_LIB)/WinNetConfigSharedStatic.lib \ - $(PATH_STAGE_LIB)/VBoxDrvCfgSharedStatic.lib \ - $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \ - $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/WbemUuid.Lib -endif if "$(KBUILD_TARGET)" == "win" && defined(VBOX_WITH_TESTCASES) && !defined(VBOX_OSE) include $(PATH_SUB_CURRENT)/testcase/Makefile.kmk diff --git a/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp b/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp index f02447bc..d76cb438 100644 --- a/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp +++ b/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp @@ -38,27 +38,28 @@ #include #include +#include "VBoxCommon.h" + +#ifndef TESTCASE +/** + * Retrieves a MSI property (in UTF-16). + * + * Convenience function for VBoxGetMsiProp(). + * + * @returns VBox status code. + * @param hMsi MSI handle to use. + * @param pwszName Name of property to retrieve. + * @param pwszValueBuf Where to store the allocated value on success. + * @param cwcValueBuf Size (in WCHARs) of \a pwszValueBuf. + */ UINT VBoxGetMsiProp(MSIHANDLE hMsi, const WCHAR *pwszName, WCHAR *pwszValueBuf, DWORD cwcValueBuf) { - RT_BZERO(pwszValueBuf, cwcValueBuf * sizeof(pwszValueBuf[0])); - - /** @todo r=bird: why do we need to query the size first and then the data. - * The API should be perfectly capable of doing that without our help. */ - DWORD cwcNeeded = 0; - UINT uiRet = MsiGetPropertyW(hMsi, pwszName, L"", &cwcNeeded); - if (uiRet == ERROR_MORE_DATA) - { - ++cwcNeeded; /* On output does not include terminating null, so add 1. */ - - if (cwcNeeded > cwcValueBuf) - return ERROR_MORE_DATA; - uiRet = MsiGetPropertyW(hMsi, pwszName, pwszValueBuf, &cwcNeeded); - } - return uiRet; + RT_BZERO(pwszValueBuf, cwcValueBuf * sizeof(WCHAR)); + return MsiGetPropertyW(hMsi, pwszName, pwszValueBuf, &cwcValueBuf); } +#endif -#if 0 /* unused */ /** * Retrieves a MSI property (in UTF-8). * @@ -77,7 +78,7 @@ int VBoxGetMsiPropUtf8(MSIHANDLE hMsi, const char *pcszName, char **ppszValue) if (RT_SUCCESS(rc)) { WCHAR wszValue[1024]; /* 1024 should be enough for everybody (tm). */ - if (VBoxGetMsiProp(hMsi, pwszName, wszValue, sizeof(wszValue)) == ERROR_SUCCESS) + if (VBoxGetMsiProp(hMsi, pwszName, wszValue, RT_ELEMENTS(wszValue)) == ERROR_SUCCESS) rc = RTUtf16ToUtf8(wszValue, ppszValue); else rc = VERR_NOT_FOUND; @@ -87,12 +88,13 @@ int VBoxGetMsiPropUtf8(MSIHANDLE hMsi, const char *pcszName, char **ppszValue) return rc; } -#endif +#ifndef TESTCASE UINT VBoxSetMsiProp(MSIHANDLE hMsi, const WCHAR *pwszName, const WCHAR *pwszValue) { return MsiSetPropertyW(hMsi, pwszName, pwszValue); } +#endif UINT VBoxSetMsiPropDWORD(MSIHANDLE hMsi, const WCHAR *pwszName, DWORD dwVal) { diff --git a/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp b/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp index f82f0848..d4ac6104 100644 --- a/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp +++ b/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp @@ -29,22 +29,24 @@ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ -#ifdef VBOX_WITH_NETFLT +#if defined(VBOX_WITH_NETFLT) || defined(VBOX_WITH_NETADP) # include "VBox/VBoxNetCfg-win.h" # include "VBox/VBoxDrvCfg-win.h" #endif -#include -#include - #define _WIN32_DCOM #include +#include +#include +#include + #include #define INITGUID #include #include #include +#include /* For ConvertSidToStringSidW. */ #include #include @@ -54,9 +56,14 @@ #include #include +#include +#include +#include #include #include /* RTPATH_MAX, RTPATH_IS_SLASH */ #include /* RT_ZERO */ +#include +#include #include #include "VBoxCommon.h" @@ -78,6 +85,48 @@ #define MY_WTEXT(a_str) MY_WTEXT_HLP(a_str) +/********************************************************************************************************************************* +* Internal structures * +*********************************************************************************************************************************/ +/** + * Structure for keeping a target's directory security context. + */ +typedef struct TGTDIRSECCTX +{ + /** Initialized status. */ + bool fInitialized; + /** Handle of the target's parent directory. + * + * Kept open while the context is around and initialized. */ + RTDIR hParentDir; + /** Absolute (resolved) path of the target directory. */ + char szTargetDirAbs[RTPATH_MAX]; + /** Access mask which is forbidden for an ACE of type ACCESS_ALLOWED_ACE_TYPE. */ + uint32_t fAccessMaskForbidden; + /** Array of well-known SIDs which are forbidden. */ + PSID *paWellKnownSidsForbidden; + /** Number of entries in \a paWellKnownSidsForbidden. */ + size_t cWellKnownSidsForbidden; +} TGTDIRSECCTX; +/** Pointer to a target's directory security context. */ +typedef TGTDIRSECCTX *PTGTDIRSECCTX; + + +/********************************************************************************************************************************* +* Prototypes * +*********************************************************************************************************************************/ +static void destroyTargetDirSecurityCtx(PTGTDIRSECCTX pCtx); + + +/********************************************************************************************************************************* +* Globals * +*********************************************************************************************************************************/ +static uint32_t g_cRef = 0; +/** Our target directory security context. + * + * Has to be global in order to keep it around as long as the DLL is being loaded. */ +static TGTDIRSECCTX g_TargetDirSecCtx = { 0 }; + /** * DLL entry point. @@ -86,59 +135,94 @@ BOOL WINAPI DllMain(HANDLE hInst, ULONG uReason, LPVOID pReserved) { RT_NOREF(hInst, uReason, pReserved); -#if 0 - /* - * This is a trick for allowing the debugger to be attached, don't know if - * there is an official way to do that, but this is a pretty efficient. - * - * Monitor the debug output in DbgView and be ready to start windbg when - * the message below appear. This will happen 3-4 times during install, - * and 2-3 times during uninstall. - * - * Note! The DIFxApp.DLL will automatically trigger breakpoints when a - * debugger is attached. Just continue on these. - */ - if (uReason == DLL_PROCESS_ATTACH) +#ifdef DEBUG + WCHAR wszMsg[128]; + RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "DllMain: hInst=%#x, uReason=%u (PID %u), g_cRef=%RU32\n", + hInst, uReason, GetCurrentProcessId(), g_cRef); + OutputDebugStringW(wszMsg); +#endif + + switch (uReason) { - WCHAR wszMsg[128]; - RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "Waiting for debugger to attach: windbg -g -G -p %u\n", GetCurrentProcessId()); - for (unsigned i = 0; i < 128 && !IsDebuggerPresent(); i++) + case DLL_PROCESS_ATTACH: + { + g_cRef++; +#if 0 + /* + * This is a trick for allowing the debugger to be attached, don't know if + * there is an official way to do that, but this is a pretty efficient. + * + * Monitor the debug output in DbgView and be ready to start windbg when + * the message below appear. This will happen 3-4 times during install, + * and 2-3 times during uninstall. + * + * Note! The DIFxApp.DLL will automatically trigger breakpoints when a + * debugger is attached. Just continue on these. + */ + RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "Waiting for debugger to attach: windbg -g -G -p %u\n", GetCurrentProcessId()); + for (unsigned i = 0; i < 128 && !IsDebuggerPresent(); i++) + { + OutputDebugStringW(wszMsg); + Sleep(1001); + } + Sleep(1002); + __debugbreak(); +#endif + break; + } + + case DLL_PROCESS_DETACH: { - OutputDebugStringW(wszMsg); - Sleep(1001); + g_cRef--; + break; } - Sleep(1002); - __debugbreak(); + + default: + break; } -#endif return TRUE; } /** - * Format and add message to the MSI log. + * Format a log message and print it to whatever is there (i.e. to the MSI log). * * UTF-16 strings are formatted using '%ls' (lowercase). * ANSI strings are formatted using '%s' (uppercase). + * + * @returns VBox status code. + * @param hInstall MSI installer handle. Optional and can be NULL. + * @param pszFmt Format string. + * @param ... Variable arguments for format string. */ -static UINT logStringF(MSIHANDLE hInstall, const char *pszFmt, ...) +static int logStringF(MSIHANDLE hInstall, const char *pszFmt, ...) { + RTUTF16 wszVa[RTPATH_MAX + 256]; + va_list va; + va_start(va, pszFmt); + ssize_t cwc = RTUtf16PrintfV(wszVa, RT_ELEMENTS(wszVa), pszFmt, va); + va_end(va); + + RTUTF16 wszMsg[RTPATH_MAX + 256]; + cwc = RTUtf16Printf(wszMsg, sizeof(wszMsg), "VBoxInstallHelper: %ls", wszVa); + if (cwc <= 0) + return VERR_BUFFER_OVERFLOW; + +#ifdef DEBUG + OutputDebugStringW(wszMsg); +#endif +#ifdef TESTCASE + RTPrintf("%ls\n", wszMsg); +#endif PMSIHANDLE hMSI = MsiCreateRecord(2 /* cParms */); if (hMSI) { - wchar_t wszBuf[RTPATH_MAX + 256]; - va_list va; - va_start(va, pszFmt); - ssize_t cwc = RTUtf16PrintfV(wszBuf, RT_ELEMENTS(wszBuf), pszFmt, va); - va_end(va); - - MsiRecordSetStringW(hMSI, 0, wszBuf); + MsiRecordSetStringW(hMSI, 0, wszMsg); MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), hMSI); - MsiCloseHandle(hMSI); - return cwc < RT_ELEMENTS(wszBuf) ? ERROR_SUCCESS : ERROR_BUFFER_OVERFLOW; } - return ERROR_ACCESS_DENIED; + + return cwc < RT_ELEMENTS(wszVa) ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW; } UINT __stdcall IsSerialCheckNeeded(MSIHANDLE hModule) @@ -161,6 +245,483 @@ UINT __stdcall CheckSerial(MSIHANDLE hModule) return ERROR_SUCCESS; } +/** + * Initializes a target security context. + * + * @returns VBox status code. + * @param pCtx Target directory security context to initialize. + * @param hModule Windows installer module handle. + * @param pszPath Target directory path to use. + */ +static int initTargetDirSecurityCtx(PTGTDIRSECCTX pCtx, MSIHANDLE hModule, const char *pszPath) +{ + if (pCtx->fInitialized) + return VINF_SUCCESS; + +#ifdef DEBUG + logStringF(hModule, "initTargetDirSecurityCtx: pszPath=%s\n", pszPath); +#endif + + char szPathTemp[RTPATH_MAX]; + int vrc = RTStrCopy(szPathTemp, sizeof(szPathTemp), pszPath); + if (RT_FAILURE(vrc)) + return vrc; + + /* Try to find a parent path which exists. */ + char szPathParentAbs[RTPATH_MAX] = { 0 }; + for (int i = 0; i < 256; i++) /* Failsafe counter. */ + { + RTPathStripTrailingSlash(szPathTemp); + RTPathStripFilename(szPathTemp); + vrc = RTPathReal(szPathTemp, szPathParentAbs, sizeof(szPathParentAbs)); + if (RT_SUCCESS(vrc)) + break; + } + + if (RT_FAILURE(vrc)) + { + logStringF(hModule, "initTargetDirSecurityCtx: No existing / valid parent directory found (%Rrc), giving up\n", vrc); + return vrc; + } + + RTDIR hParentDir; + vrc = RTDirOpen(&hParentDir, szPathParentAbs); + if (RT_FAILURE(vrc)) + { + logStringF(hModule, "initTargetDirSecurityCtx: Locking parent directory '%s' failed with %Rrc\n", szPathParentAbs, vrc); + return vrc; + } + +#ifdef DEBUG + logStringF(hModule, "initTargetDirSecurityCtx: Locked parent directory '%s'\n", szPathParentAbs); +#endif + + char szPathTargetAbs[RTPATH_MAX]; + vrc = RTPathReal(pszPath, szPathTargetAbs, sizeof(szPathTargetAbs)); + if (RT_FAILURE(vrc)) + vrc = RTStrCopy(szPathTargetAbs, sizeof(szPathTargetAbs), pszPath); + if (RT_FAILURE(vrc)) + { + logStringF(hModule, "initTargetDirSecurityCtx: Failed to resolve absolute target path (%Rrc)\n", vrc); + return vrc; + } + +#ifdef DEBUG + logStringF(hModule, "initTargetDirSecurityCtx: szPathTargetAbs=%s, szPathParentAbs=%s\n", szPathTargetAbs, szPathParentAbs); +#endif + + /* Target directory validation. */ + if ( !RTStrCmp(szPathTargetAbs, szPathParentAbs) /* Don't allow installation into root directories. */ + || RTStrStr(szPathTargetAbs, "..")) + { + logStringF(hModule, "initTargetDirSecurityCtx: Directory '%s' invalid", szPathTargetAbs); + vrc = VERR_INVALID_NAME; + } + + if (RT_SUCCESS(vrc)) + { + RTFSOBJINFO fsObjInfo; + vrc = RTPathQueryInfo(szPathParentAbs, &fsObjInfo, RTFSOBJATTRADD_NOTHING); + if (RT_SUCCESS(vrc)) + { + if (RTFS_IS_DIRECTORY(fsObjInfo.Attr.fMode)) /* No symlinks or other fun stuff. */ + { + static WELL_KNOWN_SID_TYPE aForbiddenWellKnownSids[] = + { + WinNullSid, + WinWorldSid, + WinAuthenticatedUserSid, + WinBuiltinUsersSid, + WinBuiltinGuestsSid, + WinBuiltinPowerUsersSid + }; + + pCtx->paWellKnownSidsForbidden = (PSID *)RTMemAlloc(sizeof(PSID) * RT_ELEMENTS(aForbiddenWellKnownSids)); + AssertPtrReturn(pCtx->paWellKnownSidsForbidden, VERR_NO_MEMORY); + + size_t i = 0; + for(; i < RT_ELEMENTS(aForbiddenWellKnownSids); i++) + { + pCtx->paWellKnownSidsForbidden[i] = RTMemAlloc(SECURITY_MAX_SID_SIZE); + AssertPtrBreakStmt(pCtx->paWellKnownSidsForbidden, vrc = VERR_NO_MEMORY); + DWORD cbSid = SECURITY_MAX_SID_SIZE; + if (!CreateWellKnownSid(aForbiddenWellKnownSids[i], NULL, pCtx->paWellKnownSidsForbidden[i], &cbSid)) + { + vrc = RTErrConvertFromWin32(GetLastError()); + logStringF(hModule, "initTargetDirSecurityCtx: Creating SID (index %zu) failed with %Rrc\n", i, vrc); + break; + } + } + + if (RT_SUCCESS(vrc)) + { + vrc = RTStrCopy(pCtx->szTargetDirAbs, sizeof(pCtx->szTargetDirAbs), szPathTargetAbs); + if (RT_SUCCESS(vrc)) + { + pCtx->fInitialized = true; + pCtx->hParentDir = hParentDir; + pCtx->cWellKnownSidsForbidden = i; + pCtx->fAccessMaskForbidden = FILE_WRITE_DATA + | FILE_APPEND_DATA + | FILE_WRITE_ATTRIBUTES + | FILE_WRITE_EA; + + RTFILE fh; + RTFileOpen(&fh, "c:\\temp\\targetdir.ctx", RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE); + RTFileClose(fh); + + return VINF_SUCCESS; + } + } + } + else + vrc = VERR_INVALID_NAME; + } + } + + RTDirClose(hParentDir); + + while (pCtx->cWellKnownSidsForbidden--) + { + RTMemFree(pCtx->paWellKnownSidsForbidden[pCtx->cWellKnownSidsForbidden]); + pCtx->paWellKnownSidsForbidden[pCtx->cWellKnownSidsForbidden] = NULL; + } + + logStringF(hModule, "initTargetDirSecurityCtx: Initialization failed failed with %Rrc\n", vrc); + return vrc; +} + +/** + * Destroys a target security context. + * + * @returns VBox status code. + * @param pCtx Target directory security context to destroy. + */ +static void destroyTargetDirSecurityCtx(PTGTDIRSECCTX pCtx) +{ + if ( !pCtx + || !pCtx->fInitialized) + return; + + if (pCtx->hParentDir != NIL_RTDIR) + { + RTDirClose(pCtx->hParentDir); + pCtx->hParentDir = NIL_RTDIR; + } + RT_ZERO(pCtx->szTargetDirAbs); + + for (size_t i = 0; i < pCtx->cWellKnownSidsForbidden; i++) + RTMemFree(pCtx->paWellKnownSidsForbidden[i]); + pCtx->cWellKnownSidsForbidden = 0; + + RTMemFree(pCtx->paWellKnownSidsForbidden); + pCtx->paWellKnownSidsForbidden = NULL; + + RTFileDelete("c:\\temp\\targetdir.ctx"); + + logStringF(NULL, "destroyTargetDirSecurityCtx\n"); +} + +#ifdef DEBUG +/** + * Returns a stingified version of an ACE type. + * + * @returns Stingified version of an ACE type. + * @param uType ACE type. + */ +inline const char *dbgAceTypeToString(uint8_t uType) +{ + switch (uType) + { + RT_CASE_RET_STR(ACCESS_ALLOWED_ACE_TYPE); + RT_CASE_RET_STR(ACCESS_DENIED_ACE_TYPE); + RT_CASE_RET_STR(SYSTEM_AUDIT_ACE_TYPE); + RT_CASE_RET_STR(SYSTEM_ALARM_ACE_TYPE); + default: break; + } + + return ""; +} + +/** + * Returns an allocated string for a SID containing the user/domain name. + * + * @returns Allocated string (UTF-8). Must be free'd using RTStrFree(). + * @param pSid SID to return allocated string for. + */ +inline char *dbgSidToNameA(const PSID pSid) +{ + char *pszName = NULL; + int vrc = VINF_SUCCESS; + + LPWSTR pwszSid = NULL; + if (ConvertSidToStringSid(pSid, &pwszSid)) + { + SID_NAME_USE SidNameUse; + + WCHAR wszUser[MAX_PATH]; + DWORD cbUser = sizeof(wszUser); + WCHAR wszDomain[MAX_PATH]; + DWORD cbDomain = sizeof(wszDomain); + if (LookupAccountSid(NULL, pSid, wszUser, &cbUser, wszDomain, &cbDomain, &SidNameUse)) + { + RTUTF16 wszName[RTPATH_MAX]; + if (RTUtf16Printf(wszName, RT_ELEMENTS(wszName), "%ls%s%ls (%ls)", + wszUser, wszDomain[0] == L'\0' ? "" : "\\", wszDomain, pwszSid)) + { + vrc = RTUtf16ToUtf8(wszName, &pszName); + } + else + vrc = VERR_NO_MEMORY; + } + else + vrc = RTStrAPrintf(&pszName, ""); + + LocalFree(pwszSid); + } + else + vrc = VERR_NOT_FOUND; + + return RT_SUCCESS(vrc) ? pszName : ""; +} +#endif /* DEBUG */ + +/** + * Checks a single target path whether it's safe to use or not. + * + * We check if the given path is owned by "NT Service\TrustedInstaller" and therefore assume that it's safe to use. + * + * @returns VBox status code. On error the path should be considered unsafe. + * @retval VERR_INVALID_NAME if the given path is considered unsafe. + * @retval VINF_SUCCESS if the given path is found to be safe to use. + * @param hModule Windows installer module handle. + * @param pszPath Path to check. + */ +static int checkTargetDirOne(MSIHANDLE hModule, PTGTDIRSECCTX pCtx, const char *pszPath) +{ + logStringF(hModule, "checkTargetDirOne: Checking '%s' ...", pszPath); + + PRTUTF16 pwszPath; + int vrc = RTStrToUtf16(pszPath, &pwszPath); + if (RT_FAILURE(vrc)) + return vrc; + + PACL pDacl = NULL; + PSECURITY_DESCRIPTOR pSecurityDescriptor = { 0 }; + DWORD dwErr = GetNamedSecurityInfo(pwszPath, SE_FILE_OBJECT, GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + NULL, NULL, NULL, NULL, &pSecurityDescriptor); + if (dwErr == ERROR_SUCCESS) + { + BOOL fDaclPresent = FALSE; + BOOL fDaclDefaultedIgnored = FALSE; + if (GetSecurityDescriptorDacl(pSecurityDescriptor, &fDaclPresent, + &pDacl, &fDaclDefaultedIgnored)) + { + if ( !fDaclPresent + || !pDacl) + { + /* Bail out early if the DACL isn't provided or is missing. */ + vrc = VERR_INVALID_NAME; + } + else + { + ACL_SIZE_INFORMATION aclSizeInfo; + RT_ZERO(aclSizeInfo); + if (GetAclInformation(pDacl, &aclSizeInfo, sizeof(aclSizeInfo), AclSizeInformation)) + { + for(DWORD idxACE = 0; idxACE < aclSizeInfo.AceCount; idxACE++) + { + ACE_HEADER *pAceHdr = NULL; + if (GetAce(pDacl, idxACE, (LPVOID *)&pAceHdr)) + { +#ifdef DEBUG + logStringF(hModule, "checkTargetDirOne: ACE type=%s, flags=%#x, size=%#x", + dbgAceTypeToString(pAceHdr->AceType), pAceHdr->AceFlags, pAceHdr->AceSize); +#endif + /* Note: We print the ACEs in canonoical order. */ + switch (pAceHdr->AceType) + { + case ACCESS_ALLOWED_ACE_TYPE: /* We're only interested in the ALLOW ACE. */ + { + ACCESS_ALLOWED_ACE const *pAce = (ACCESS_ALLOWED_ACE *)pAceHdr; + PSID const pSid = (PSID)&pAce->SidStart; +#ifdef DEBUG + char *pszSid = dbgSidToNameA(pSid); + logStringF(hModule, "checkTargetDirOne:\t%s fMask=%#x", pszSid, pAce->Mask); + RTStrFree(pszSid); +#endif + /* We check the flags here first for performance reasons. */ + if ((pAce->Mask & pCtx->fAccessMaskForbidden) == pCtx->fAccessMaskForbidden) + { + for (size_t idxSID = 0; idxSID < pCtx->cWellKnownSidsForbidden; idxSID++) + { + PSID const pSidForbidden = pCtx->paWellKnownSidsForbidden[idxSID]; + bool const fForbidden = EqualSid(pSid, pSidForbidden); +#ifdef DEBUG + char *pszName = dbgSidToNameA(pSidForbidden); + logStringF(hModule, "checkTargetDirOne:\t%s : %s", + fForbidden ? "** FORBIDDEN **" : "ALLOWED ", pszName); + RTStrFree(pszName); +#endif /* DEBUG */ + if (fForbidden) + { + vrc = VERR_INVALID_NAME; + break; + } + } + } + + break; + } +#ifdef DEBUG + case ACCESS_DENIED_ACE_TYPE: /* We're only interested in the ALLOW ACE. */ + { + ACCESS_DENIED_ACE const *pAce = (ACCESS_DENIED_ACE *)pAceHdr; + + LPWSTR pwszSid = NULL; + ConvertSidToStringSid((PSID)&pAce->SidStart, &pwszSid); + + logStringF(hModule, "checkTargetDirOne:\t%ls fMask=%#x (generic %#x specific %#x)", + pwszSid ? pwszSid : L"", pAce->Mask); + + LocalFree(pwszSid); + break; + } +#endif /* DEBUG */ + default: + /* Ignore everything else. */ + break; + } + } + else + dwErr = GetLastError(); + + /* No point in checking further if we failed somewhere above. */ + if (RT_FAILURE(vrc)) + break; + + } /* for ACE */ + } + else + dwErr = GetLastError(); + } + } + else + dwErr = GetLastError(); + + LocalFree(pSecurityDescriptor); + } + else + dwErr = GetLastError(); + + if (RT_SUCCESS(vrc)) + vrc = RTErrConvertFromWin32(dwErr); + +#ifdef DEBUG + logStringF(hModule, "checkTargetDirOne: Returning %Rrc", vrc); +#endif + + if ( RT_FAILURE(vrc) + && vrc != VERR_INVALID_NAME) + logStringF(hModule, "checkTargetDirOne: Failed with %Rrc (%#x)", vrc, dwErr); + + return vrc; +} + +/** + * Checks whether the path in the public property INSTALLDIR has the correct ACL permissions and returns whether + * it's valid or not. + * + * Called from the MSI installer as a custom action. + * + * @returns Success status (acccording to MSI custom actions). + * @retval ERROR_SUCCESS if checking the target directory turned out to be valid. + * @retval ERROR_NO_NET_OR_BAD_PATH is the target directory is invalid. + * @param hModule Windows installer module handle. + * + * @note Sets private property VBox_Target_Dir_Is_Valid to "1" (true) if the given target path is valid, + * or "0" (false) if it is not. An empty target directory is considered to be valid (i.e. INSTALLDIR not set yet). + * + * @sa @bugref{10616} + */ +UINT __stdcall CheckTargetDir(MSIHANDLE hModule) +{ + char *pszTargetDir; + + int vrc = VBoxGetMsiPropUtf8(hModule, "INSTALLDIR", &pszTargetDir); + if (RT_SUCCESS(vrc)) + { + logStringF(hModule, "CheckTargetDir: Checking target directory '%s' ...", pszTargetDir); + + if (!RTStrNLen(pszTargetDir, RTPATH_MAX)) + { + logStringF(hModule, "CheckTargetDir: No INSTALLDIR set (yet), skipping ..."); + VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"1"); + } + else + { + union + { + RTPATHPARSED Parsed; + uint8_t ab[RTPATH_MAX]; + } u; + + vrc = RTPathParse(pszTargetDir, &u.Parsed, sizeof(u), RTPATH_STR_F_STYLE_DOS); + if (RT_SUCCESS(vrc)) + { + if (u.Parsed.fProps & RTPATH_PROP_DOTDOT_REFS) + vrc = VERR_INVALID_PARAMETER; + if (RT_SUCCESS(vrc)) + { + vrc = initTargetDirSecurityCtx(&g_TargetDirSecCtx, hModule, pszTargetDir); + if (RT_SUCCESS(vrc)) + { + uint16_t idxComp = u.Parsed.cComps; + char szPathToCheck[RTPATH_MAX]; + while (idxComp > 1) /* We traverse backwards from INSTALLDIR and leave out the root (e.g. C:\"). */ + { + u.Parsed.cComps = idxComp; + vrc = RTPathParsedReassemble(pszTargetDir, &u.Parsed, RTPATH_STR_F_STYLE_DOS, + szPathToCheck, sizeof(szPathToCheck)); + if (RT_FAILURE(vrc)) + break; + if (RTDirExists(szPathToCheck)) + { + vrc = checkTargetDirOne(hModule, &g_TargetDirSecCtx, szPathToCheck); + if (RT_FAILURE(vrc)) + break; + } + else + logStringF(hModule, "CheckTargetDir: Path '%s' does not exist (yet)", szPathToCheck); + idxComp--; + } + + destroyTargetDirSecurityCtx(&g_TargetDirSecCtx); + } + else + logStringF(hModule, "CheckTargetDir: initTargetDirSecurityCtx failed with %Rrc\n", vrc); + + if (RT_SUCCESS(vrc)) + VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"1"); + } + } + else + logStringF(hModule, "CheckTargetDir: Parsing path failed with %Rrc", vrc); + } + + RTStrFree(pszTargetDir); + } + + if (RT_FAILURE(vrc)) /* On failure (or when in doubt), mark the installation directory as invalid. */ + { + logStringF(hModule, "CheckTargetDir: Checking failed with %Rrc", vrc); + VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"0"); + } + + /* Return back outcome to the MSI engine. */ + return RT_SUCCESS(vrc) ? ERROR_SUCCESS : ERROR_NO_NET_OR_BAD_PATH; +} + /** * Runs an executable on the OS. * @@ -869,7 +1430,7 @@ UINT __stdcall InstallBranding(MSIHANDLE hModule) return ERROR_SUCCESS; /* Do not fail here. */ } -#ifdef VBOX_WITH_NETFLT +#if defined(VBOX_WITH_NETFLT) || defined(VBOX_WITH_NETADP) /** @todo should use some real VBox app name */ #define VBOX_NETCFG_APP_NAME L"VirtualBox Installer" @@ -1051,7 +1612,9 @@ static UINT doNetCfgInit(MSIHANDLE hModule, INetCfg **ppnc, BOOL bWrite) return uErr; } +#endif /* defined(VBOX_WITH_NETFLT) || defined(VBOX_WITH_NETADP) */ +#ifdef VBOX_WITH_NETFLT static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR pwszPtInf, DWORD cwcPtInf, OUT LPWSTR pwszMpInf, DWORD cwcMpInf) { @@ -1082,11 +1645,8 @@ static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR pwszPtInf, DWO return uErr; } -#endif /*VBOX_WITH_NETFLT*/ - -/*static*/ UINT _uninstallNetFlt(MSIHANDLE hModule) +static UINT _uninstallNetFlt(MSIHANDLE hModule) { -#ifdef VBOX_WITH_NETFLT INetCfg *pNetCfg; UINT uErr; @@ -1123,21 +1683,26 @@ static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR pwszPtInf, DWO } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETFLT */ UINT __stdcall UninstallNetFlt(MSIHANDLE hModule) { - (void)_uninstallNetLwf(hModule); +#ifdef VBOX_WITH_NETFLT + _uninstallNetLwf(hModule); return _uninstallNetFlt(hModule); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETFLT static UINT _installNetFlt(MSIHANDLE hModule) { -#ifdef VBOX_WITH_NETFLT UINT uErr; INetCfg *pNetCfg; @@ -1184,22 +1749,26 @@ static UINT _installNetFlt(MSIHANDLE hModule) } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the install even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETFLT */ UINT __stdcall InstallNetFlt(MSIHANDLE hModule) { - (void)_uninstallNetLwf(hModule); +#ifdef VBOX_WITH_NETFLT + _uninstallNetLwf(hModule); return _installNetFlt(hModule); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } - -/*static*/ UINT _uninstallNetLwf(MSIHANDLE hModule) -{ #ifdef VBOX_WITH_NETFLT +static UINT _uninstallNetLwf(MSIHANDLE hModule) +{ INetCfg *pNetCfg; UINT uErr; @@ -1236,21 +1805,26 @@ UINT __stdcall InstallNetFlt(MSIHANDLE hModule) } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETFLT */ UINT __stdcall UninstallNetLwf(MSIHANDLE hModule) { - (void)_uninstallNetFlt(hModule); +#ifdef VBOX_WITH_NETFLT + _uninstallNetFlt(hModule); return _uninstallNetLwf(hModule); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETFLT static UINT _installNetLwf(MSIHANDLE hModule) { -#ifdef VBOX_WITH_NETFLT UINT uErr; INetCfg *pNetCfg; @@ -1313,20 +1887,25 @@ static UINT _installNetLwf(MSIHANDLE hModule) } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the install even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETFLT */ UINT __stdcall InstallNetLwf(MSIHANDLE hModule) { - (void)_uninstallNetFlt(hModule); +#ifdef VBOX_WITH_NETFLT + _uninstallNetFlt(hModule); return _installNetLwf(hModule); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } -#if 0 +#if 0 /** @todo r=andy Remove this? */ static BOOL RenameHostOnlyConnectionsCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext) { WCHAR DevName[256]; @@ -1382,11 +1961,11 @@ static BOOL RenameHostOnlyConnectionsCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DAT return TRUE; } -#endif +#endif /* 0 */ +#ifdef VBOX_WITH_NETADP static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR pwszInfName) { -#ifdef VBOX_WITH_NETFLT netCfgLoggerEnable(hModule); BOOL fSetupModeInteractive = SetupSetNonInteractiveMode(FALSE); @@ -1455,12 +2034,12 @@ static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR //in fail case call CreateHostOnlyInterface logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinUpdateHostOnlyNetworkInterface failed, hr = %#x", hr); logStringF(hModule, "CreateHostOnlyInterface: calling VBoxNetCfgWinCreateHostOnlyNetworkInterface"); -#ifdef VBOXNETCFG_DELAYEDRENAME +# ifdef VBOXNETCFG_DELAYEDRENAME BSTR devId; hr = VBoxNetCfgWinCreateHostOnlyNetworkInterface(pwszInfPath, fIsFile, NULL, &guid, &devId, NULL); -#else /* !VBOXNETCFG_DELAYEDRENAME */ +# else /* !VBOXNETCFG_DELAYEDRENAME */ hr = VBoxNetCfgWinCreateHostOnlyNetworkInterface(pwszInfPath, fIsFile, NULL, &guid, NULL, NULL); -#endif /* !VBOXNETCFG_DELAYEDRENAME */ +# endif /* !VBOXNETCFG_DELAYEDRENAME */ logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface returns %#x", hr); if (SUCCEEDED(hr)) { @@ -1471,12 +2050,12 @@ static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig returns %#x", hr); if (FAILED(hr)) logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig failed, error = %#x", hr); -#ifdef VBOXNETCFG_DELAYEDRENAME +# ifdef VBOXNETCFG_DELAYEDRENAME hr = VBoxNetCfgWinRenameHostOnlyConnection(&guid, devId, NULL); if (FAILED(hr)) logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinRenameHostOnlyConnection failed, error = %#x", hr); SysFreeString(devId); -#endif /* VBOXNETCFG_DELAYEDRENAME */ +# endif /* VBOXNETCFG_DELAYEDRENAME */ } else logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface failed, error = %#x", hr); @@ -1493,21 +2072,26 @@ static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR netCfgLoggerDisable(); -#endif /* VBOX_WITH_NETFLT */ - logStringF(hModule, "CreateHostOnlyInterface: Returns success (ignoring all failures)"); /* Never fail the install even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall CreateHostOnlyInterface(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _createHostOnlyInterface(hModule, NETADP_ID, L"VBoxNetAdp.inf"); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } UINT __stdcall Ndis6CreateHostOnlyInterface(MSIHANDLE hModule) { -#if 0 /* Trick for allowing the debugger to be attached. */ +#ifdef VBOX_WITH_NETADP +# if 0 /* Trick for allowing the debugger to be attached. */ for (unsigned i = 0; i < 128 && !IsDebuggerPresent(); i++) { logStringF(hModule, "Waiting for debugger to attach: windbg -p %u", GetCurrentProcessId()); @@ -1515,13 +2099,17 @@ UINT __stdcall Ndis6CreateHostOnlyInterface(MSIHANDLE hModule) } Sleep(1002); __debugbreak(); -#endif +# endif return _createHostOnlyInterface(hModule, NETADP_ID, L"VBoxNetAdp6.inf"); +#else /* !VBOX_WITH_NETADP */ + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETADP static UINT _removeHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId) { -#ifdef VBOX_WITH_NETFLT netCfgLoggerEnable(hModule); logStringF(hModule, "RemoveHostOnlyInterfaces: Removing all host-only interfaces"); @@ -1545,20 +2133,25 @@ static UINT _removeHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId) SetupSetNonInteractiveMode(fSetupModeInteractive); netCfgLoggerDisable(); -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall RemoveHostOnlyInterfaces(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _removeHostOnlyInterfaces(hModule, NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETADP static UINT _stopHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId) { -#ifdef VBOX_WITH_NETFLT netCfgLoggerEnable(hModule); logStringF(hModule, "StopHostOnlyInterfaces: Stopping all host-only interfaces"); @@ -1576,20 +2169,25 @@ static UINT _stopHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId) SetupSetNonInteractiveMode(fSetupModeInteractive); netCfgLoggerDisable(); -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall StopHostOnlyInterfaces(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _stopHostOnlyInterfaces(hModule, NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETADP static UINT _updateHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszInfName, LPCWSTR pwszId) { -#ifdef VBOX_WITH_NETFLT netCfgLoggerEnable(hModule); logStringF(hModule, "UpdateHostOnlyInterfaces: Updating all host-only interfaces"); @@ -1656,25 +2254,35 @@ static UINT _updateHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszInfName, LP SetupSetNonInteractiveMode(fSetupModeInteractive); netCfgLoggerDisable(); -#endif /* VBOX_WITH_NETFLT */ /* Never fail the update even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall UpdateHostOnlyInterfaces(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _updateHostOnlyInterfaces(hModule, L"VBoxNetAdp.inf", NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } UINT __stdcall Ndis6UpdateHostOnlyInterfaces(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _updateHostOnlyInterfaces(hModule, L"VBoxNetAdp6.inf", NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETADP static UINT _uninstallNetAdp(MSIHANDLE hModule, LPCWSTR pwszId) { -#ifdef VBOX_WITH_NETFLT INetCfg *pNetCfg; UINT uErr; @@ -1711,15 +2319,20 @@ static UINT _uninstallNetAdp(MSIHANDLE hModule, LPCWSTR pwszId) } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall UninstallNetAdp(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _uninstallNetAdp(hModule, NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } static bool isTAPDevice(const WCHAR *pwszGUID) diff --git a/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def b/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def index 03cb5d60..3ab891c1 100644 --- a/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def +++ b/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def @@ -29,6 +29,7 @@ LIBRARY "VBoxInstallHelper" EXPORTS IsSerialCheckNeeded CheckSerial + CheckTargetDir IsMSCRTInstalled IsPythonInstalled IsWindows10 @@ -38,8 +39,8 @@ EXPORTS UninstallBranding InstallNetFlt UninstallNetFlt - UninstallNetAdp - InstallNetLwf + UninstallNetAdp + InstallNetLwf UninstallNetLwf UninstallTAPInstances UninstallVBoxDrv diff --git a/src/VBox/Installer/win/NLS/de_DE.wxl b/src/VBox/Installer/win/NLS/de_DE.wxl index dcd4d3e1..d4b004f1 100644 --- a/src/VBox/Installer/win/NLS/de_DE.wxl +++ b/src/VBox/Installer/win/NLS/de_DE.wxl @@ -63,8 +63,7 @@ [ProductName] Treiber für virtuellen Netzwerk-Adapter für Host-only Netzwerke. [ProductName] Treiber für NDIS6-Netzwerkbrücke. [ProductName] Treiber für virtuellen Netzwerk-Adapter für NDIS6-Host-only-Netzwerke. - - Python-Support für VirtualBox. + Python-Support für VirtualBox. @@ -75,6 +74,7 @@ Diese Applikation läuft nur auf 64-bit Windows-Systemen. Bitte installieren Sie die 32-bit Version von [ProductName]! Eine alte Sun Version von VirtualBox wurde auf diesem Computer gefunden. Bitte deinstallieren Sie diese Version zuerst. Danach können Sie [ProductName] installieren! Eine alte innotek Version von VirtualBox wurde auf diesem Computer gefunden. Bitte deinstallieren Sie diese Version zuerst. Danach können Sie [ProductName] installieren! + Ungültiges Installationsverzeichnis angegeben. Bitte ein anderes Installationsverzeichnis wählen, um [ProductName] zu installieren. @@ -92,6 +92,11 @@ Ich &akzeptiere die Bedingungen des Lizenzvertrags. Ich &akzeptiere die Bedingungen des Lizenzvertrags nicht. + + Ungültiges Installationsverzeichnis + Das gewählte Installationsverzeichnis is ungültig, da dieses nicht den Sicherheitsrichtlinien entspricht. + Bitte ein anderes Installationsverzeichnis wählen um [ProductName] zu installieren. + Seriennummer diff --git a/src/VBox/Installer/win/NLS/el_GR.wxl b/src/VBox/Installer/win/NLS/el_GR.wxl index 8d98eab9..071a61e0 100644 --- a/src/VBox/Installer/win/NLS/el_GR.wxl +++ b/src/VBox/Installer/win/NLS/el_GR.wxl @@ -63,7 +63,6 @@ Οδηγός [ProductName] εικονικής κάρτας δικτύου για μόνο-με-οικοδεσπότη δίκτυα. Οδηγός [ProductName] για NDIS6 γεφυρωμένα δίκτυα. Οδηγός [ProductName] εικονικής κάρτας δικτύου για NDIS6 μόνο-με-οικοδεσπότη δίκτυα. - Υποστήριξη Python για το VirtualBox. @@ -75,6 +74,7 @@ Αυτή η εφαρμογή τρέχει μόνο σε συστήματα Windows 64 bit. Εγκαταστήστε την έκδοση 32-bit του [ProductName]! Βρέθηκε μία παλιότερη εγκατάσταση του Sun VirtualBox στον υπολογιστή. Καταργήστε πρώτα την εγκατάσταση αυτού του πακέτου και μετά εγκαταστήστε το [ProductName]! Βρέθηκε μία παλιότερη εγκατάσταση του innotek VirtualBox στον υπολογιστή. Καταργήστε πρώτα την εγκατάσταση αυτού του πακέτου και μετά εγκαταστήστε το [ProductName]! + Invalid installation directory specified! Please use another installation directory to install [ProductName]. @@ -94,6 +94,12 @@ + Invalid installation directory + The chosen installation directory is invalid, as it does not meet the security requirements. + Please choose another directory for installing [ProductName]. + + + Σειριακός Αριθμός Εισάγετε τον σειριακό αριθμό σας στα παρακάτω πεδία. Θα το βρείτε στο αυτοκόλλητο μέσα στην θήκη του CD του VirtualBox. Όταν ολοκληρώσετε την εισαγωγή του σειριακού αριθμού, πατήστε το κουμπί "Check" παρακάτω. diff --git a/src/VBox/Installer/win/NLS/en_US.wxl b/src/VBox/Installer/win/NLS/en_US.wxl index b3be4e45..3eac3530 100644 --- a/src/VBox/Installer/win/NLS/en_US.wxl +++ b/src/VBox/Installer/win/NLS/en_US.wxl @@ -63,7 +63,6 @@ [ProductName] virtual network adapter driver for Host-Only Networking. [ProductName] driver for NDIS6 Bridged Networking. [ProductName] virtual network adapter driver for NDIS6 Host-Only Networking. - Python support for VirtualBox. @@ -75,6 +74,7 @@ This application only runs on 64-bit Windows systems. Please install the 32-bit version of [ProductName]! An old Sun VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]! An old innotek VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]! + Invalid installation directory specified! Please use another installation directory to install [ProductName]. @@ -94,6 +94,12 @@ + Invalid installation directory + The chosen installation directory is invalid, as it does not meet the security requirements. + Please choose another directory for installing [ProductName]. + + + Serial Number Please enter your serial number in the fields below. You'll find it on the sticker inside the VirtualBox CD case. When done entering the serial number, press the "Check" button below. diff --git a/src/VBox/Installer/win/NLS/fa_IR.wxl b/src/VBox/Installer/win/NLS/fa_IR.wxl index f6b0173a..1eeedf8a 100644 --- a/src/VBox/Installer/win/NLS/fa_IR.wxl +++ b/src/VBox/Installer/win/NLS/fa_IR.wxl @@ -58,8 +58,7 @@ درایور آداپتور شبکه مجازی [ProductName] برای شبکه فقط-میزبان. [ProductName] driver for NDIS6 Bridged Networking. [ProductName] virtual network adapter driver for NDIS6 Host-Only Networking. - - پشتیبانی از پایتون برای ویرچوال باکس. + پشتیبانی از پایتون برای ویرچوال باکس. برای حذف [ProductName] شما نیاز به اجازه مدیر دارید! این راه انداز حالا لغو میشود. [ProductName] needs the Microsoft Visual C++ 2019 Redistributable Package being installed first. Please install and restart the installation of [ProductName]. @@ -68,6 +67,7 @@ این برنامه فقط روی ویندوز 64 بیتی اِجرا میشود. لطفا نسخه 32 بیتی [ProductName] را نصب کنید! یک نصب قدیمی ویرچوال باکس روی این رایانه یافت شد. لطفا اول این بسته را حذف سپس [ProductName] را نصب کنید! یک نسخه قدیمی نصب ویرچوال باکس در این ماشین یافت شد. لطفا اول این بسته را حذف و سپس [ProductName] را نصب کنید! + Invalid installation directory specified! Please use another installation directory to install [ProductName]. آیا میخواهید نصب [ProductName] را لغو کنید؟ @@ -79,6 +79,10 @@ &من ضوابط را در توافقنامه مجوز می پذیرم &من ضوابط را در توافقنامه مجوز نمی پذیرم + Invalid installation directory + The chosen installation directory is invalid, as it does not meet the security requirements. + Please choose another directory for installing [ProductName]. + شماره سریال لطفا شماره سریال را در فیلد زیر وارد کنید.آن را روی برچسب روی جلد سی دی ویرچوال باکس می یابید. وقتی که وارد کردن شماره سریال انجام شد،دکمه "بررسی" را در زیر فشار دهید. diff --git a/src/VBox/Installer/win/NLS/fr_FR.wxl b/src/VBox/Installer/win/NLS/fr_FR.wxl index 773786c5..2624925b 100644 --- a/src/VBox/Installer/win/NLS/fr_FR.wxl +++ b/src/VBox/Installer/win/NLS/fr_FR.wxl @@ -63,8 +63,7 @@ Pilote de carte réseau virtuelle [ProductName] pour l'accès réseau privé hôte. [ProductName] driver for NDIS6 Bridged Networking. [ProductName] virtual network adapter driver for NDIS6 Host-Only Networking. - - Python support for VirtualBox. + Python support for VirtualBox. @@ -74,6 +73,7 @@ Cette application ne marche que sur des systèmes Windows 32-bit. Veuillez installer la version 64-bit de [ProductName]! Cette application ne marche que sur des systèmes Windows 64-bit. Veuillez installer la version 32-bit de [ProductName]! Vous avez une ancienne installation de innotek VirtualBox sur cette machine. Il vous faudra la désinstaller avant de pouvoir installer [ProductName]. + Invalid installation directory specified! Please use another installation directory to install [ProductName]. @@ -93,6 +93,12 @@ + Invalid installation directory + The chosen installation directory is invalid, as it does not meet the security requirements. + Please choose another directory for installing [ProductName]. + + + Numéro de série Veulliez entrer votre numéro de série dans les champs ci-dessous. Vous le trouverez sur l'autocollant à l'intérieur du boîtier du CD de VirtualBox. Quand vous avez fini d'entrer le numéro de série, appuyez sur le bouton Vérifier ci-dessous. diff --git a/src/VBox/Installer/win/NLS/it_IT.wxl b/src/VBox/Installer/win/NLS/it_IT.wxl index adead2a5..ef0b25d5 100644 --- a/src/VBox/Installer/win/NLS/it_IT.wxl +++ b/src/VBox/Installer/win/NLS/it_IT.wxl @@ -58,8 +58,7 @@ Driver di [ProductName] per la scheda di rete virtuale per la rete solo host. Driver di [ProductName] per la rete con bridge NDIS6. Driver di [ProductName] per la scheda di rete virtuale per la rete solo host NDIS6. - - Supporto Python per VirtualBox. + Supporto Python per VirtualBox. Devi avere diritti di amministrazione per (dis)installare [ProductName]! L'installazione sarà interrotta immediatamente. [ProductName] needs the Microsoft Visual C++ 2019 Redistributable Package being installed first. Please install and restart the installation of [ProductName]. @@ -68,6 +67,7 @@ Questa applicazione può essere eseguita solo su sistemi Windows a 64 bit. Installa la versione a 32 bit di [ProductName]! Una vecchia installazione di Sun VirtualBox è stata trovata su questa macchina. Disinstalla prima questo pacchetto e poi installa [ProductName]! Una vecchia installazione di innotek VirtualBox è stata trovata su questa macchina. Disinstalla prima questo pacchetto e poi installa [ProductName]! + Invalid installation directory specified! Please use another installation directory to install [ProductName]. Sei sicuro di voler annullare l'installazione di [ProductName]? @@ -79,6 +79,10 @@ &Accetto i termini dell'accordo di licenza &Non accetto i termini dell'accordo di licenza + Invalid installation directory + The chosen installation directory is invalid, as it does not meet the security requirements. + Please choose another directory for installing [ProductName]. + Numero di serie Digita il numero di serie nel campo seguente. Troverai il numero sull'adesivo all'interno della custodia del CD di VirtualBox. Una volta digitato il numero di serie, premi il pulsante "Controlla" in basso. diff --git a/src/VBox/Installer/win/NLS/ru_RU.wxl b/src/VBox/Installer/win/NLS/ru_RU.wxl index b3be4e45..3eac3530 100644 --- a/src/VBox/Installer/win/NLS/ru_RU.wxl +++ b/src/VBox/Installer/win/NLS/ru_RU.wxl @@ -63,7 +63,6 @@ [ProductName] virtual network adapter driver for Host-Only Networking. [ProductName] driver for NDIS6 Bridged Networking. [ProductName] virtual network adapter driver for NDIS6 Host-Only Networking. - Python support for VirtualBox. @@ -75,6 +74,7 @@ This application only runs on 64-bit Windows systems. Please install the 32-bit version of [ProductName]! An old Sun VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]! An old innotek VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]! + Invalid installation directory specified! Please use another installation directory to install [ProductName]. @@ -94,6 +94,12 @@ + Invalid installation directory + The chosen installation directory is invalid, as it does not meet the security requirements. + Please choose another directory for installing [ProductName]. + + + Serial Number Please enter your serial number in the fields below. You'll find it on the sticker inside the VirtualBox CD case. When done entering the serial number, press the "Check" button below. diff --git a/src/VBox/Installer/win/NLS/tr_TR.wxl b/src/VBox/Installer/win/NLS/tr_TR.wxl index 2604eff9..ff7a3b89 100644 --- a/src/VBox/Installer/win/NLS/tr_TR.wxl +++ b/src/VBox/Installer/win/NLS/tr_TR.wxl @@ -63,8 +63,7 @@ Yalnızca-Anamakine Ağı Oluşturma için [ProductName] sanal ağ bağdaştırıcısı sürücüsü. NDIS6 Köprü Ağı Oluşturma için [ProductName] sürücüsü. NDIS6 Yalnızca-Anamakine Ağı Oluşturma için [ProductName] sanal ağ bağdaştırıcısı sürücüsü. - - VirtualBox için Python desteği. + VirtualBox için Python desteği. @@ -75,6 +74,7 @@ Bu uygulama yalnızca 64-bit Windows sistemlerinde çalışır. Lütfen [ProductName] 32-bit sürümünü yükleyin! Bu makinede eski bir Sun VirtualBox kurulumu bulundu. Lütfen önce bu paketi kaldırın ve sonra [ProductName] yükleyin! Bu makinede eski bir innotek VirtualBox kurulumu bulundu. Lütfen önce bu paketi kaldırın ve sonra [ProductName] yükleyin! + Invalid installation directory specified! Please use another installation directory to install [ProductName]. @@ -94,6 +94,12 @@ + Invalid installation directory + The chosen installation directory is invalid, as it does not meet the security requirements. + Please choose another directory for installing [ProductName]. + + + Seri Numarası Lütfen aşağıdaki alana seri numaranızı girin. VirtualBox CD kutusu içerisindeki etikette bulacaksınız. Seri numarasını girmeniz bittiğinde, aşağıdaki "Denetle" düğmesine basın". diff --git a/src/VBox/Installer/win/NLS/zh_CN.wxl b/src/VBox/Installer/win/NLS/zh_CN.wxl index 7ea1c68c..2d57834a 100644 --- a/src/VBox/Installer/win/NLS/zh_CN.wxl +++ b/src/VBox/Installer/win/NLS/zh_CN.wxl @@ -63,7 +63,6 @@ [ProductName] 虚拟网络界面卡针对“仅主机”网络。 [ProductName] driver for NDIS6 Bridged Networking. [ProductName] virtual network adapter driver for NDIS6 Host-Only Networking. - VirtualBox 的 Python 支持。 @@ -75,6 +74,7 @@ 此应用程序只能运行在 64 位 Windows 系统。 请安装 [ProductName] 的 32 位版本! 在此计算机发现旧的 Sun VirtualBox 安装。 请先卸载此组件然后安装 [ProductName]! 在此计算机发现旧的 innotek VirtualBox 安装。 请先卸载此组件然后安装 [ProductName]! +Invalid installation directory specified! Please use another installation directory to install [ProductName]. @@ -94,6 +94,12 @@ +Invalid installation directory +The chosen installation directory is invalid, as it does not meet the security requirements. +Please choose another directory for installing [ProductName]. + + + 序号 请在以下字段输入你的序号。 你可以在 VirtualBox CD 盒内的贴纸找到。 序号输入完成时,单击以下"检查"按钮。 diff --git a/src/VBox/Installer/win/NLS/zh_TW.wxl b/src/VBox/Installer/win/NLS/zh_TW.wxl index cc7da673..c30e8113 100644 --- a/src/VBox/Installer/win/NLS/zh_TW.wxl +++ b/src/VBox/Installer/win/NLS/zh_TW.wxl @@ -63,7 +63,6 @@ [ProductName] 虛擬網路介面卡針對「僅限主機」網路。 [ProductName] 驅動程式針對 NDIS6 橋接網路。 [ProductName] 虛擬網路介面卡針對 NDIS6 「僅限主機」網路。 - VirtualBox 的 Python 支援。 @@ -75,6 +74,7 @@ 此應用程式只能執行在 64 位元的 Windows 系統。 請安裝 [ProductName] 的 32 位元版本! 在此電腦發現舊的 Sun VirtualBox 安裝。 請先解除安裝此套件然後安裝 [ProductName]! 在此電腦發現舊的 innotek VirtualBox 安裝。 請先解除安裝此套件然後安裝 [ProductName]! + Invalid installation directory specified! Please use another installation directory to install [ProductName]. @@ -94,6 +94,12 @@ + Invalid installation directory + The chosen installation directory is invalid, as it does not meet the security requirements. + Please choose another directory for installing [ProductName]. + + + 序號 請在以下欄位輸入您的序號。 您可以在 VirtualBox CD 盒內的貼紙找到。 序號輸入完成時,按一下以下「檢查」按鈕。 diff --git a/src/VBox/Installer/win/UserInterface.wxi b/src/VBox/Installer/win/UserInterface.wxi index f371cd55..c3bbab13 100644 --- a/src/VBox/Installer/win/UserInterface.wxi +++ b/src/VBox/Installer/win/UserInterface.wxi @@ -206,6 +206,43 @@ + + + + + + + + + {\DlgInvalidSerial}!(loc.InvalidTargetDirDlg_Header) + + + + + !(loc.InvalidTargetDirDlg_Desc1) + + + + !(loc.InvalidTargetDirDlg_Desc2) + + + + + + + + [Version_text] $(var.Property_Version) + + + + + + + 1 + + + + @@ -220,7 +257,7 @@ !(loc.CustomizeDlg_IconTree) - 1 @@ -465,18 +502,12 @@ - - - 1 - 1 - - - 1 - 1 - + + + + Property="VBOX_TARGET_DIR" Indirect="yes" Fixed="yes" Remote="yes"> @@ -487,7 +518,7 @@ 1 + Property="VBOX_TARGET_DIR" Sunken="yes" Indirect="yes" TabSkip="no" /> @@ -1177,15 +1208,33 @@ 1 - - - - - - - - - + 1 + 1 + 1 + 1 + + 1 + + + + + 1 + + + + + + + + + + + + + + @@ -1211,6 +1260,7 @@ + diff --git a/src/VBox/Installer/win/VBoxMergeAppCA.wxi b/src/VBox/Installer/win/VBoxMergeAppCA.wxi index ddc29f5e..2a3eef7f 100644 --- a/src/VBox/Installer/win/VBoxMergeAppCA.wxi +++ b/src/VBox/Installer/win/VBoxMergeAppCA.wxi @@ -35,5 +35,11 @@ + + + + diff --git a/src/VBox/Installer/win/VBoxMergeAppSeq.wxi b/src/VBox/Installer/win/VBoxMergeAppSeq.wxi index b6340cef..6b7c3a1f 100644 --- a/src/VBox/Installer/win/VBoxMergeAppSeq.wxi +++ b/src/VBox/Installer/win/VBoxMergeAppSeq.wxi @@ -30,6 +30,11 @@ 1 + + + + 1 diff --git a/src/VBox/Installer/win/VirtualBox.wxs b/src/VBox/Installer/win/VirtualBox.wxs index 1e4911cc..beccd815 100644 --- a/src/VBox/Installer/win/VirtualBox.wxs +++ b/src/VBox/Installer/win/VirtualBox.wxs @@ -127,6 +127,11 @@ Installed OR (VBOX_MSCRT_INSTALLED) + + + Installed OR (VBox_Target_Dir_Is_Valid="1") + -- cgit v1.2.3