From ea864b56d115e4f7a7205827ecaaba0e1db81d41 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Mon, 31 Dec 2018 23:57:35 -0600 Subject: Integrate into latest v4. --- src/Cpp.Build.props | 100 ++++ src/Directory.Build.props | 26 + src/Directory.Build.targets | 48 ++ src/FindLocalWix.props | 8 + src/mbahost/host.cpp | 656 --------------------- src/mbahost/host.def | 6 - src/mbahost/host.vcxproj | 51 -- src/mbahost/mbahost.cpp | 656 +++++++++++++++++++++ src/mbahost/mbahost.def | 6 + src/mbahost/mbahost.vcxproj | 64 ++ src/mbahost/packages.config | 7 + src/mbahost/precomp.cpp | 3 + src/wixext/BalBinder.cs | 125 ---- src/wixext/BalCompiler.cs | 266 +++++---- src/wixext/BalErrors.cs | 55 ++ src/wixext/BalExtensionData.cs | 45 +- src/wixext/BalExtensionFactory.cs | 18 + src/wixext/BalWarnings.cs | 31 + .../BalWindowsInstallerBackendBinderExtension.cs | 146 +++++ src/wixext/Tuples/BalTupleDefinitions.cs | 55 ++ src/wixext/Tuples/WixBalBAFunctionsTuple.cs | 47 ++ src/wixext/Tuples/WixBalConditionTuple.cs | 55 ++ src/wixext/Tuples/WixMbaPrereqInformationTuple.cs | 63 ++ src/wixext/Tuples/WixStdbaOptionsTuple.cs | 79 +++ .../Tuples/WixStdbaOverridableVariableTuple.cs | 47 ++ src/wixext/WixBalExtension.csproj | 47 -- src/wixext/WixToolset.Bal.wixext.csproj | 30 + src/wixext/WixToolset.Bal.wixext.targets | 11 + src/wixext/messages.xml | 43 -- src/wixlib/BalExtension.wixproj | 39 -- src/wixlib/bal.wixproj | 62 ++ src/wixlib/packages.config | 5 + src/wixstdba/packages.config | 7 + src/wixstdba/precomp.cpp | 3 + src/wixstdba/precomp.h | 5 + src/wixstdba/wixstdba.vcxproj | 41 +- 36 files changed, 1807 insertions(+), 1149 deletions(-) create mode 100644 src/Cpp.Build.props create mode 100644 src/Directory.Build.props create mode 100644 src/Directory.Build.targets create mode 100644 src/FindLocalWix.props delete mode 100644 src/mbahost/host.cpp delete mode 100644 src/mbahost/host.def delete mode 100644 src/mbahost/host.vcxproj create mode 100644 src/mbahost/mbahost.cpp create mode 100644 src/mbahost/mbahost.def create mode 100644 src/mbahost/mbahost.vcxproj create mode 100644 src/mbahost/packages.config create mode 100644 src/mbahost/precomp.cpp delete mode 100644 src/wixext/BalBinder.cs create mode 100644 src/wixext/BalErrors.cs create mode 100644 src/wixext/BalExtensionFactory.cs create mode 100644 src/wixext/BalWarnings.cs create mode 100644 src/wixext/BalWindowsInstallerBackendBinderExtension.cs create mode 100644 src/wixext/Tuples/BalTupleDefinitions.cs create mode 100644 src/wixext/Tuples/WixBalBAFunctionsTuple.cs create mode 100644 src/wixext/Tuples/WixBalConditionTuple.cs create mode 100644 src/wixext/Tuples/WixMbaPrereqInformationTuple.cs create mode 100644 src/wixext/Tuples/WixStdbaOptionsTuple.cs create mode 100644 src/wixext/Tuples/WixStdbaOverridableVariableTuple.cs delete mode 100644 src/wixext/WixBalExtension.csproj create mode 100644 src/wixext/WixToolset.Bal.wixext.csproj create mode 100644 src/wixext/WixToolset.Bal.wixext.targets delete mode 100644 src/wixext/messages.xml delete mode 100644 src/wixlib/BalExtension.wixproj create mode 100644 src/wixlib/bal.wixproj create mode 100644 src/wixlib/packages.config create mode 100644 src/wixstdba/packages.config create mode 100644 src/wixstdba/precomp.cpp (limited to 'src') diff --git a/src/Cpp.Build.props b/src/Cpp.Build.props new file mode 100644 index 00000000..296b36ca --- /dev/null +++ b/src/Cpp.Build.props @@ -0,0 +1,100 @@ + + + + + + Win32 + $(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\ + $(OutputPath)$(Platform)\ + + + + + $(DisableSpecificCompilerWarnings) + Level4 + $(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) + Use + precomp.h + StdCall + true + false + -YlprecompDefine + /Zc:threadSafeInit- %(AdditionalOptions) + true + + + $(ArmPreprocessorDefinitions);%(PreprocessorDefinitions) + $(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories) + + + $(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories) + + + $(ProjectSubSystem) + $(ProjectModuleDefinitionFile) + $(ResourceOnlyDll) + true + $(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies) + $(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories) + /IGNORE:4099 %(AdditionalOptions) + + + + + + NoExtensions + + + + + CDecl + + + + + OldStyle + true + true + + + + + Disabled + EnableFastChecks + _DEBUG;DEBUG;%(PreprocessorDefinitions) + MultiThreadedDebug + + + + + + MultiThreadedDebugDll + + + + + MinSpace + NDEBUG;%(PreprocessorDefinitions) + true + true + MultiThreaded + + + true + true + + + + + + MultiThreadedDll + + + + + $(LinkKeyFile) + $(LinkDelaySign) + + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 00000000..e853e22d --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,26 @@ + + + + + + Debug + false + + $(MSBuildProjectName) + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\)) + $(BaseOutputPath)obj\$(ProjectName)\ + $(BaseOutputPath)$(Configuration)\ + + WiX Toolset Team + WiX Toolset + Copyright (c) .NET Foundation and contributors. All rights reserved. + MS-RL + WiX Toolset + + + + + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets new file mode 100644 index 00000000..dac7452a --- /dev/null +++ b/src/Directory.Build.targets @@ -0,0 +1,48 @@ + + + + + + + true + $(SolutionPath) + $(NCrunchOriginalSolutionPath) + + + + + + + $([System.IO.File]::ReadAllText($(TheSolutionPath))) + $([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) )) + (?<="[PackageName]", ")(.*)(?=", ") + + + + + + %(Identity) + $(SolutionFileContent.Contains('\%(Identity).csproj')) + + + + + $(RegexPattern.Replace('[PackageName]','%(PackageName)') ) + $([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)')) + + + + + + + + + + + diff --git a/src/FindLocalWix.props b/src/FindLocalWix.props new file mode 100644 index 00000000..a784e352 --- /dev/null +++ b/src/FindLocalWix.props @@ -0,0 +1,8 @@ + + + + + + $(MSBuildThisFileDirectory)..\..\Tools\build\Debug\net461\wix.targets + + diff --git a/src/mbahost/host.cpp b/src/mbahost/host.cpp deleted file mode 100644 index 694db357..00000000 --- a/src/mbahost/host.cpp +++ /dev/null @@ -1,656 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -#include "precomp.h" -#include // includes the generated assembly name macros. -#include "BalBaseBootstrapperApplicationProc.h" - -static const DWORD NET452_RELEASE = 379893; - -using namespace mscorlib; - -extern "C" typedef HRESULT (WINAPI *PFN_CORBINDTOCURRENTRUNTIME)( - __in LPCWSTR pwszFileName, - __in REFCLSID rclsid, - __in REFIID riid, - __out LPVOID *ppv - ); - -extern "C" typedef HRESULT(WINAPI *PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE)( - __in HRESULT hrHostInitialization, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults - ); - -static HINSTANCE vhInstance = NULL; -static ICorRuntimeHost *vpCLRHost = NULL; -static _AppDomain *vpAppDomain = NULL; -static HMODULE vhMbapreqModule = NULL; - - -// internal function declarations - -static HRESULT GetAppDomain( - __out _AppDomain** ppAppDomain - ); -static HRESULT GetAppBase( - __out LPWSTR* psczAppBase - ); -static HRESULT CheckSupportedFrameworks( - __in LPCWSTR wzConfigPath - ); -static HRESULT UpdateSupportedRuntime( - __in IXMLDOMDocument* pixdManifest, - __in IXMLDOMNode* pixnSupportedFramework, - __out BOOL* pfUpdatedManifest - ); -static HRESULT GetCLRHost( - __in LPCWSTR wzConfigPath, - __out ICorRuntimeHost** ppCLRHost - ); -static HRESULT CreateManagedBootstrapperApplication( - __in _AppDomain* pAppDomain, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults - ); -static HRESULT CreateManagedBootstrapperApplicationFactory( - __in _AppDomain* pAppDomain, - __out IBootstrapperApplicationFactory** ppAppFactory - ); -static HRESULT CreatePrerequisiteBA( - __in HRESULT hrHostInitialization, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults - ); -static HRESULT VerifyNET4RuntimeIsSupported( - ); - - -// function definitions - -extern "C" BOOL WINAPI DllMain( - IN HINSTANCE hInstance, - IN DWORD dwReason, - IN LPVOID /* pvReserved */ - ) -{ - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - ::DisableThreadLibraryCalls(hInstance); - vhInstance = hInstance; - break; - - case DLL_PROCESS_DETACH: - vhInstance = NULL; - break; - } - - return TRUE; -} - -// Note: This function assumes that COM was already initialized on the thread. -extern "C" HRESULT WINAPI BootstrapperApplicationCreate( - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults - ) -{ - HRESULT hr = S_OK; - HRESULT hrHostInitialization = S_OK; - IBootstrapperEngine* pEngine = NULL; - - hr = BalInitializeFromCreateArgs(pArgs, &pEngine); - ExitOnFailure(hr, "Failed to initialize Bal."); - - hr = GetAppDomain(&vpAppDomain); - if (SUCCEEDED(hr)) - { - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application."); - - hr = CreateManagedBootstrapperApplication(vpAppDomain, pEngine, pArgs, pResults); - BalExitOnFailure(hr, "Failed to create the managed bootstrapper application."); - } - else // fallback to the prerequisite BA. - { - if (E_MBAHOST_NET452_ON_WIN7RTM == hr) - { - BalLogError(hr, "The Burn engine cannot run with an MBA under the .NET 4 CLR on Windows 7 RTM with .NET 4.5.2 (or greater) installed."); - hrHostInitialization = hr; - } - else - { - hrHostInitialization = S_OK; - } - - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr); - - hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, pArgs, pResults); - BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); - } - -LExit: - return hr; -} - -extern "C" void WINAPI BootstrapperApplicationDestroy() -{ - if (vpAppDomain) - { - HRESULT hr = vpCLRHost->UnloadDomain(vpAppDomain); - if (FAILED(hr)) - { - BalLogError(hr, "Failed to unload app domain."); - } - - vpAppDomain->Release(); - } - - if (vpCLRHost) - { - vpCLRHost->Stop(); - vpCLRHost->Release(); - } - - if (vhMbapreqModule) - { - PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast(::GetProcAddress(vhMbapreqModule, "MbaPrereqBootstrapperApplicationDestroy")); - if (pfnDestroy) - { - (*pfnDestroy)(); - } - - ::FreeLibrary(vhMbapreqModule); - vhMbapreqModule = NULL; - } - - BalUninitialize(); -} - -// Gets the custom AppDomain for loading managed BA. -static HRESULT GetAppDomain( - __out _AppDomain **ppAppDomain - ) -{ - HRESULT hr = S_OK; - ICorRuntimeHost *pCLRHost = NULL; - IUnknown *pUnk = NULL; - LPWSTR sczAppBase = NULL; - LPWSTR sczConfigPath = NULL; - IAppDomainSetup *pAppDomainSetup; - BSTR bstrAppBase = NULL; - BSTR bstrConfigPath = NULL; - - hr = GetAppBase(&sczAppBase); - ExitOnFailure(hr, "Failed to get the host base path."); - - hr = PathConcat(sczAppBase, L"BootstrapperCore.config", &sczConfigPath); - ExitOnFailure(hr, "Failed to get the full path to the application configuration file."); - - // Check that the supported framework is installed. - hr = CheckSupportedFrameworks(sczConfigPath); - ExitOnFailure(hr, "Failed to find supported framework."); - - // Load the CLR. - hr = GetCLRHost(sczConfigPath, &pCLRHost); - ExitOnFailure(hr, "Failed to create the CLR host."); - - hr = pCLRHost->Start(); - ExitOnRootFailure(hr, "Failed to start the CLR host."); - - // Create the setup information for a new AppDomain to set the app base and config. - hr = pCLRHost->CreateDomainSetup(&pUnk); - ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object."); - - hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast(&pAppDomainSetup)); - ExitOnRootFailure(hr, "Failed to query for the IAppDomainSetup interface."); - ReleaseNullObject(pUnk); - - // Set properties on the AppDomainSetup object. - bstrAppBase = ::SysAllocString(sczAppBase); - ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup."); - - hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase); - ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup."); - - bstrConfigPath = ::SysAllocString(sczConfigPath); - ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup."); - - hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath); - ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup."); - - // Create the AppDomain to load the factory type. - hr = pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk); - ExitOnRootFailure(hr, "Failed to create the MBA AppDomain."); - - hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast(ppAppDomain)); - ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface."); - -LExit: - ReleaseBSTR(bstrConfigPath); - ReleaseBSTR(bstrAppBase); - ReleaseStr(sczConfigPath); - ReleaseStr(sczAppBase); - ReleaseNullObject(pUnk); - ReleaseNullObject(pCLRHost); - - return hr; -} - -static HRESULT GetAppBase( - __out LPWSTR *psczAppBase - ) -{ - HRESULT hr = S_OK; - LPWSTR sczFullPath = NULL; - - hr = PathForCurrentProcess(&sczFullPath, vhInstance); - ExitOnFailure(hr, "Failed to get the full host path."); - - hr = PathGetDirectory(sczFullPath, psczAppBase); - ExitOnFailure(hr, "Failed to get the directory of the full process path."); - -LExit: - ReleaseStr(sczFullPath); - - return hr; -} - -// Checks whether at least one of required supported frameworks is installed via the NETFX registry keys. -static HRESULT CheckSupportedFrameworks( - __in LPCWSTR wzConfigPath - ) -{ - HRESULT hr = S_OK; - IXMLDOMDocument* pixdManifest = NULL; - IXMLDOMNodeList* pNodeList = NULL; - IXMLDOMNode* pNode = NULL; - DWORD cSupportedFrameworks = 0; - LPWSTR sczSupportedFrameworkVersion = NULL; - LPWSTR sczFrameworkRegistryKey = NULL; - HKEY hkFramework = NULL; - DWORD dwFrameworkInstalled = 0; - BOOL fUpdatedManifest = FALSE; - - hr = XmlInitialize(); - ExitOnFailure(hr, "Failed to initialize XML."); - - hr = XmlLoadDocumentFromFile(wzConfigPath, &pixdManifest); - ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", wzConfigPath); - - hr = XmlSelectNodes(pixdManifest, L"/configuration/wix.bootstrapper/host/supportedFramework", &pNodeList); - ExitOnFailure(hr, "Failed to select all supportedFramework elements."); - - hr = pNodeList->get_length(reinterpret_cast(&cSupportedFrameworks)); - ExitOnFailure(hr, "Failed to get the supported framework count."); - - if (cSupportedFrameworks) - { - while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, NULL))) - { - hr = XmlGetAttributeEx(pNode, L"version", &sczSupportedFrameworkVersion); - ExitOnFailure(hr, "Failed to get supportedFramework/@version."); - - hr = StrAllocFormatted(&sczFrameworkRegistryKey, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\%ls", sczSupportedFrameworkVersion); - ExitOnFailure(hr, "Failed to allocate path to supported framework Install registry key."); - - hr = RegOpen(HKEY_LOCAL_MACHINE, sczFrameworkRegistryKey, KEY_READ, &hkFramework); - if (SUCCEEDED(hr)) - { - hr = RegReadNumber(hkFramework, L"Install", &dwFrameworkInstalled); - if (dwFrameworkInstalled) - { - hr = S_OK; - break; - } - } - - ReleaseNullObject(pNode); - } - - // If we looped through all the supported frameworks but didn't find anything, ensure we return a failure. - if (S_FALSE == hr) - { - hr = E_NOTFOUND; - ExitOnRootFailure(hr, "Failed to find a supported framework."); - } - - hr = UpdateSupportedRuntime(pixdManifest, pNode, &fUpdatedManifest); - ExitOnFailure(hr, "Failed to update supportedRuntime."); - } - // else no supported frameworks specified, so the startup/supportedRuntime must be enough. - - if (fUpdatedManifest) - { - hr = XmlSaveDocument(pixdManifest, wzConfigPath); - ExitOnFailure(hr, "Failed to save updated manifest over config file: %ls", wzConfigPath); - } - -LExit: - ReleaseRegKey(hkFramework); - ReleaseStr(sczFrameworkRegistryKey); - ReleaseStr(sczSupportedFrameworkVersion); - ReleaseObject(pNode); - ReleaseObject(pNodeList); - ReleaseObject(pixdManifest); - - XmlUninitialize(); - - return hr; -} - -// Fixes the supportedRuntime element if necessary. -static HRESULT UpdateSupportedRuntime( - __in IXMLDOMDocument* pixdManifest, - __in IXMLDOMNode* pixnSupportedFramework, - __out BOOL* pfUpdatedManifest - ) -{ - HRESULT hr = S_OK; - LPWSTR sczSupportedRuntimeVersion = NULL; - IXMLDOMNode* pixnStartup = NULL; - IXMLDOMNode* pixnSupportedRuntime = NULL; - - *pfUpdatedManifest = FALSE; - - // If the runtime version attribute is not specified, don't update the manifest. - hr = XmlGetAttributeEx(pixnSupportedFramework, L"runtimeVersion", &sczSupportedRuntimeVersion); - if (E_NOTFOUND == hr) - { - ExitFunction1(hr = S_OK); - } - ExitOnFailure(hr, "Failed to get supportedFramework/@runtimeVersion."); - - // Get the startup element. Fail if we can't find it since it'll be necessary to load the - // correct runtime. - hr = XmlSelectSingleNode(pixdManifest, L"/configuration/startup", &pixnStartup); - ExitOnFailure(hr, "Failed to get startup element."); - - if (S_FALSE == hr) - { - hr = E_NOTFOUND; - ExitOnRootFailure(hr, "Failed to find startup element in bootstrapper application config."); - } - - // Remove any pre-existing supported runtimes because they'll just get in the way and create our new one. - hr = XmlRemoveChildren(pixnStartup, L"supportedRuntime"); - ExitOnFailure(hr, "Failed to remove pre-existing supportedRuntime elements."); - - hr = XmlCreateChild(pixnStartup, L"supportedRuntime", &pixnSupportedRuntime); - ExitOnFailure(hr, "Failed to create supportedRuntime element."); - - hr = XmlSetAttribute(pixnSupportedRuntime, L"version", sczSupportedRuntimeVersion); - ExitOnFailure(hr, "Failed to set supportedRuntime/@version to '%ls'.", sczSupportedRuntimeVersion); - - *pfUpdatedManifest = TRUE; - -LExit: - ReleaseObject(pixnSupportedRuntime); - ReleaseObject(pixnStartup); - ReleaseStr(sczSupportedRuntimeVersion); - - return hr; -} - -// Gets the CLR host and caches it. -static HRESULT GetCLRHost( - __in LPCWSTR wzConfigPath, - __out ICorRuntimeHost **ppCLRHost - ) -{ - HRESULT hr = S_OK; - UINT uiMode = 0; - HMODULE hModule = NULL; - BOOL fFallbackToCorBindToCurrentRuntime = TRUE; - CLRCreateInstanceFnPtr pfnCLRCreateInstance = NULL; - ICLRMetaHostPolicy* pCLRMetaHostPolicy = NULL; - IStream* pCfgStream = NULL; - LPWSTR pwzVersion = NULL; - DWORD cchVersion = 0; - DWORD dwConfigFlags = 0; - ICLRRuntimeInfo* pCLRRuntimeInfo = NULL; - PFN_CORBINDTOCURRENTRUNTIME pfnCorBindToCurrentRuntime = NULL; - - // Always set the error mode because we will always restore it below. - uiMode = ::SetErrorMode(0); - - // Cache the CLR host to be shutdown later. This can occur on a different thread. - if (!vpCLRHost) - { - // Disable message boxes from being displayed on error and blocking execution. - ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS); - - hr = LoadSystemLibrary(L"mscoree.dll", &hModule); - ExitOnFailure(hr, "Failed to load mscoree.dll"); - - pfnCLRCreateInstance = reinterpret_cast(::GetProcAddress(hModule, "CLRCreateInstance")); - - if (pfnCLRCreateInstance) - { - hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast(&pCLRMetaHostPolicy)); - if (E_NOTIMPL != hr) - { - ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy."); - - fFallbackToCorBindToCurrentRuntime = FALSE; - } - } - - if (fFallbackToCorBindToCurrentRuntime) - { - pfnCorBindToCurrentRuntime = reinterpret_cast(::GetProcAddress(hModule, "CorBindToCurrentRuntime")); - ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime."); - - hr = pfnCorBindToCurrentRuntime(wzConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&vpCLRHost)); - ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path."); - } - else - { - - hr = SHCreateStreamOnFileEx(wzConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream); - ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", wzConfigPath); - - hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast(&pCLRRuntimeInfo)); - ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path."); - - // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL. - if (!cchVersion) - { - hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion); - if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr) - { - ExitOnFailure(hr, "Failed to get the length of the CLR version string."); - } - } - - hr = StrAlloc(&pwzVersion, cchVersion); - ExitOnFailure(hr, "Failed to allocate the CLR version string."); - - hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion); - ExitOnFailure(hr, "Failed to get the CLR version string."); - - if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion)) - { - hr = VerifyNET4RuntimeIsSupported(); - ExitOnFailure(hr, "Found unsupported .NET 4 Runtime."); - } - - if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags)) - { - hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime(); - ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime."); - } - - hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&vpCLRHost)); - ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost."); - - // TODO: use ICLRRuntimeHost instead of ICorRuntimeHost on .NET 4 since the former is faster and the latter is deprecated - //hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, reinterpret_cast(&pCLRRuntimeHost)); - //ExitOnRootFailure(hr, "Failed to get instance of ICLRRuntimeHost."); - } - } - - vpCLRHost->AddRef(); - *ppCLRHost = vpCLRHost; - -LExit: - ReleaseStr(pwzVersion); - ReleaseNullObject(pCLRRuntimeInfo); - ReleaseNullObject(pCfgStream); - ReleaseNullObject(pCLRMetaHostPolicy); - - // Unload the module so it's not in use when we install .NET. - if (FAILED(hr)) - { - ::FreeLibrary(hModule); - } - - ::SetErrorMode(uiMode); // restore the previous error mode. - - return hr; -} - -// Creates the bootstrapper app and returns it for the engine. -static HRESULT CreateManagedBootstrapperApplication( - __in _AppDomain* pAppDomain, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults - ) -{ - HRESULT hr = S_OK; - IBootstrapperApplicationFactory* pAppFactory = NULL; - IBootstrapperApplication* pApp = NULL; - - hr = CreateManagedBootstrapperApplicationFactory(pAppDomain, &pAppFactory); - ExitOnFailure(hr, "Failed to create the factory to create the bootstrapper application."); - - hr = pAppFactory->Create(pEngine, pArgs->pCommand, &pApp); - ExitOnFailure(hr, "Failed to create the bootstrapper application."); - - pResults->pfnBootstrapperApplicationProc = BalBaseBootstrapperApplicationProc; - pResults->pvBootstrapperApplicationProcContext = pApp; - pApp = NULL; - -LExit: - ReleaseNullObject(pApp); - ReleaseNullObject(pAppFactory); - - return hr; -} - -// Creates the app factory to create the managed app in the default AppDomain. -static HRESULT CreateManagedBootstrapperApplicationFactory( - __in _AppDomain* pAppDomain, - __out IBootstrapperApplicationFactory** ppAppFactory - ) -{ - HRESULT hr = S_OK; - BSTR bstrAssemblyName = NULL; - BSTR bstrTypeName = NULL; - _ObjectHandle* pObj = NULL; - VARIANT vtBAFactory; - - ::VariantInit(&vtBAFactory); - - bstrAssemblyName = ::SysAllocString(MUX_ASSEMBLY_FULL_NAME); - ExitOnNull(bstrAssemblyName, hr, E_OUTOFMEMORY, "Failed to allocate the full assembly name for the bootstrapper application factory."); - - bstrTypeName = ::SysAllocString(L"WixToolset.Bootstrapper.BootstrapperApplicationFactory"); - ExitOnNull(bstrTypeName, hr, E_OUTOFMEMORY, "Failed to allocate the full type name for the BA factory."); - - hr = pAppDomain->CreateInstance(bstrAssemblyName, bstrTypeName, &pObj); - ExitOnRootFailure(hr, "Failed to create the BA factory object."); - - hr = pObj->Unwrap(&vtBAFactory); - ExitOnRootFailure(hr, "Failed to unwrap the BA factory object into the host domain."); - ExitOnNull(vtBAFactory.punkVal, hr, E_UNEXPECTED, "The variant did not contain the expected IUnknown pointer."); - - hr = vtBAFactory.punkVal->QueryInterface(__uuidof(IBootstrapperApplicationFactory), reinterpret_cast(ppAppFactory)); - ExitOnRootFailure(hr, "Failed to query for the bootstrapper app factory interface."); - -LExit: - ReleaseVariant(vtBAFactory); - ReleaseNullObject(pObj); - ReleaseBSTR(bstrTypeName); - ReleaseBSTR(bstrAssemblyName); - - return hr; -} - -static HRESULT CreatePrerequisiteBA( - __in HRESULT hrHostInitialization, - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, - __inout BOOTSTRAPPER_CREATE_RESULTS* pResults - ) -{ - HRESULT hr = S_OK; - LPWSTR sczMbapreqPath = NULL; - HMODULE hModule = NULL; - - hr = PathRelativeToModule(&sczMbapreqPath, L"mbapreq.dll", vhInstance); - ExitOnFailure(hr, "Failed to get path to pre-requisite BA."); - - hModule = ::LoadLibraryW(sczMbapreqPath); - ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); - - PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast(::GetProcAddress(hModule, "MbaPrereqBootstrapperApplicationCreate")); - ExitOnNullWithLastError(pfnCreate, hr, "Failed to get MbaPrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath); - - hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); - ExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); - - vhMbapreqModule = hModule; - hModule = NULL; - -LExit: - if (hModule) - { - ::FreeLibrary(hModule); - } - ReleaseStr(sczMbapreqPath); - - return hr; -} - -static HRESULT VerifyNET4RuntimeIsSupported( - ) -{ - HRESULT hr = S_OK; - OS_VERSION osv = OS_VERSION_UNKNOWN; - DWORD dwServicePack = 0; - HKEY hKey = NULL; - DWORD er = ERROR_SUCCESS; - DWORD dwRelease = 0; - DWORD cchRelease = sizeof(dwRelease); - - OsGetVersion(&osv, &dwServicePack); - if (OS_VERSION_WIN7 == osv && 0 == dwServicePack) - { - hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full", KEY_QUERY_VALUE, &hKey); - if (E_FILENOTFOUND == hr) - { - ExitFunction1(hr = S_OK); - } - ExitOnFailure(hr, "Failed to open registry key for .NET 4."); - - er = ::RegQueryValueExW(hKey, L"Release", NULL, NULL, reinterpret_cast(&dwRelease), &cchRelease); - if (ERROR_FILE_NOT_FOUND == er) - { - ExitFunction1(hr = S_OK); - } - ExitOnWin32Error(er, hr, "Failed to get Release value."); - - if (NET452_RELEASE <= dwRelease) - { - hr = E_MBAHOST_NET452_ON_WIN7RTM; - } - } - -LExit: - ReleaseRegKey(hKey); - - return hr; -} diff --git a/src/mbahost/host.def b/src/mbahost/host.def deleted file mode 100644 index 4488df94..00000000 --- a/src/mbahost/host.def +++ /dev/null @@ -1,6 +0,0 @@ -; Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - - -EXPORTS - BootstrapperApplicationCreate - BootstrapperApplicationDestroy diff --git a/src/mbahost/host.vcxproj b/src/mbahost/host.vcxproj deleted file mode 100644 index a4c3ea16..00000000 --- a/src/mbahost/host.vcxproj +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - Debug - Win32 - - - Release - Win32 - - - - - {12C87C77-3547-44F8-8134-29BC915CB19D} - DynamicLibrary - Unicode - mbahost - host.def - - - - - - $(WixRoot)src\libs\dutil\inc;$(WixRoot)src\burn\inc;$(WixRoot)src\libs\balutil\inc;$(BaseIntermediateOutputPath)\core - dutil.lib;balutil.lib;shlwapi.lib - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mbahost/mbahost.cpp b/src/mbahost/mbahost.cpp new file mode 100644 index 00000000..d3737c06 --- /dev/null +++ b/src/mbahost/mbahost.cpp @@ -0,0 +1,656 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" +#include // includes the generated assembly name macros. +#include "BalBaseBootstrapperApplicationProc.h" + +static const DWORD NET452_RELEASE = 379893; + +using namespace mscorlib; + +extern "C" typedef HRESULT (WINAPI *PFN_CORBINDTOCURRENTRUNTIME)( + __in LPCWSTR pwszFileName, + __in REFCLSID rclsid, + __in REFIID riid, + __out LPVOID *ppv + ); + +extern "C" typedef HRESULT(WINAPI *PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE)( + __in HRESULT hrHostInitialization, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ); + +static HINSTANCE vhInstance = NULL; +static ICorRuntimeHost *vpCLRHost = NULL; +static _AppDomain *vpAppDomain = NULL; +static HMODULE vhMbapreqModule = NULL; + + +// internal function declarations + +static HRESULT GetAppDomain( + __out _AppDomain** ppAppDomain + ); +static HRESULT GetAppBase( + __out LPWSTR* psczAppBase + ); +static HRESULT CheckSupportedFrameworks( + __in LPCWSTR wzConfigPath + ); +static HRESULT UpdateSupportedRuntime( + __in IXMLDOMDocument* pixdManifest, + __in IXMLDOMNode* pixnSupportedFramework, + __out BOOL* pfUpdatedManifest + ); +static HRESULT GetCLRHost( + __in LPCWSTR wzConfigPath, + __out ICorRuntimeHost** ppCLRHost + ); +static HRESULT CreateManagedBootstrapperApplication( + __in _AppDomain* pAppDomain, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ); +static HRESULT CreateManagedBootstrapperApplicationFactory( + __in _AppDomain* pAppDomain, + __out IBootstrapperApplicationFactory** ppAppFactory + ); +static HRESULT CreatePrerequisiteBA( + __in HRESULT hrHostInitialization, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ); +static HRESULT VerifyNET4RuntimeIsSupported( + ); + + +// function definitions + +extern "C" BOOL WINAPI DllMain( + IN HINSTANCE hInstance, + IN DWORD dwReason, + IN LPVOID /* pvReserved */ + ) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + ::DisableThreadLibraryCalls(hInstance); + vhInstance = hInstance; + break; + + case DLL_PROCESS_DETACH: + vhInstance = NULL; + break; + } + + return TRUE; +} + +// Note: This function assumes that COM was already initialized on the thread. +extern "C" HRESULT WINAPI BootstrapperApplicationCreate( + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ) +{ + HRESULT hr = S_OK; + HRESULT hrHostInitialization = S_OK; + IBootstrapperEngine* pEngine = NULL; + + hr = BalInitializeFromCreateArgs(pArgs, &pEngine); + ExitOnFailure(hr, "Failed to initialize Bal."); + + hr = GetAppDomain(&vpAppDomain); + if (SUCCEEDED(hr)) + { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application."); + + hr = CreateManagedBootstrapperApplication(vpAppDomain, pEngine, pArgs, pResults); + BalExitOnFailure(hr, "Failed to create the managed bootstrapper application."); + } + else // fallback to the prerequisite BA. + { + if (E_MBAHOST_NET452_ON_WIN7RTM == hr) + { + BalLogError(hr, "The Burn engine cannot run with an MBA under the .NET 4 CLR on Windows 7 RTM with .NET 4.5.2 (or greater) installed."); + hrHostInitialization = hr; + } + else + { + hrHostInitialization = S_OK; + } + + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr); + + hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, pArgs, pResults); + BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); + } + +LExit: + return hr; +} + +extern "C" void WINAPI BootstrapperApplicationDestroy() +{ + if (vpAppDomain) + { + HRESULT hr = vpCLRHost->UnloadDomain(vpAppDomain); + if (FAILED(hr)) + { + BalLogError(hr, "Failed to unload app domain."); + } + + vpAppDomain->Release(); + } + + if (vpCLRHost) + { + vpCLRHost->Stop(); + vpCLRHost->Release(); + } + + if (vhMbapreqModule) + { + PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast(::GetProcAddress(vhMbapreqModule, "MbaPrereqBootstrapperApplicationDestroy")); + if (pfnDestroy) + { + (*pfnDestroy)(); + } + + ::FreeLibrary(vhMbapreqModule); + vhMbapreqModule = NULL; + } + + BalUninitialize(); +} + +// Gets the custom AppDomain for loading managed BA. +static HRESULT GetAppDomain( + __out _AppDomain **ppAppDomain + ) +{ + HRESULT hr = S_OK; + ICorRuntimeHost *pCLRHost = NULL; + IUnknown *pUnk = NULL; + LPWSTR sczAppBase = NULL; + LPWSTR sczConfigPath = NULL; + IAppDomainSetup *pAppDomainSetup; + BSTR bstrAppBase = NULL; + BSTR bstrConfigPath = NULL; + + hr = GetAppBase(&sczAppBase); + ExitOnFailure(hr, "Failed to get the host base path."); + + hr = PathConcat(sczAppBase, L"WixToolset.BootstrapperCore.config", &sczConfigPath); + ExitOnFailure(hr, "Failed to get the full path to the application configuration file."); + + // Check that the supported framework is installed. + hr = CheckSupportedFrameworks(sczConfigPath); + ExitOnFailure(hr, "Failed to find supported framework."); + + // Load the CLR. + hr = GetCLRHost(sczConfigPath, &pCLRHost); + ExitOnFailure(hr, "Failed to create the CLR host."); + + hr = pCLRHost->Start(); + ExitOnRootFailure(hr, "Failed to start the CLR host."); + + // Create the setup information for a new AppDomain to set the app base and config. + hr = pCLRHost->CreateDomainSetup(&pUnk); + ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object."); + + hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast(&pAppDomainSetup)); + ExitOnRootFailure(hr, "Failed to query for the IAppDomainSetup interface."); + ReleaseNullObject(pUnk); + + // Set properties on the AppDomainSetup object. + bstrAppBase = ::SysAllocString(sczAppBase); + ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup."); + + hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase); + ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup."); + + bstrConfigPath = ::SysAllocString(sczConfigPath); + ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup."); + + hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath); + ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup."); + + // Create the AppDomain to load the factory type. + hr = pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk); + ExitOnRootFailure(hr, "Failed to create the MBA AppDomain."); + + hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast(ppAppDomain)); + ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface."); + +LExit: + ReleaseBSTR(bstrConfigPath); + ReleaseBSTR(bstrAppBase); + ReleaseStr(sczConfigPath); + ReleaseStr(sczAppBase); + ReleaseNullObject(pUnk); + ReleaseNullObject(pCLRHost); + + return hr; +} + +static HRESULT GetAppBase( + __out LPWSTR *psczAppBase + ) +{ + HRESULT hr = S_OK; + LPWSTR sczFullPath = NULL; + + hr = PathForCurrentProcess(&sczFullPath, vhInstance); + ExitOnFailure(hr, "Failed to get the full host path."); + + hr = PathGetDirectory(sczFullPath, psczAppBase); + ExitOnFailure(hr, "Failed to get the directory of the full process path."); + +LExit: + ReleaseStr(sczFullPath); + + return hr; +} + +// Checks whether at least one of required supported frameworks is installed via the NETFX registry keys. +static HRESULT CheckSupportedFrameworks( + __in LPCWSTR wzConfigPath + ) +{ + HRESULT hr = S_OK; + IXMLDOMDocument* pixdManifest = NULL; + IXMLDOMNodeList* pNodeList = NULL; + IXMLDOMNode* pNode = NULL; + DWORD cSupportedFrameworks = 0; + LPWSTR sczSupportedFrameworkVersion = NULL; + LPWSTR sczFrameworkRegistryKey = NULL; + HKEY hkFramework = NULL; + DWORD dwFrameworkInstalled = 0; + BOOL fUpdatedManifest = FALSE; + + hr = XmlInitialize(); + ExitOnFailure(hr, "Failed to initialize XML."); + + hr = XmlLoadDocumentFromFile(wzConfigPath, &pixdManifest); + ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", wzConfigPath); + + hr = XmlSelectNodes(pixdManifest, L"/configuration/wix.bootstrapper/host/supportedFramework", &pNodeList); + ExitOnFailure(hr, "Failed to select all supportedFramework elements."); + + hr = pNodeList->get_length(reinterpret_cast(&cSupportedFrameworks)); + ExitOnFailure(hr, "Failed to get the supported framework count."); + + if (cSupportedFrameworks) + { + while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, NULL))) + { + hr = XmlGetAttributeEx(pNode, L"version", &sczSupportedFrameworkVersion); + ExitOnFailure(hr, "Failed to get supportedFramework/@version."); + + hr = StrAllocFormatted(&sczFrameworkRegistryKey, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\%ls", sczSupportedFrameworkVersion); + ExitOnFailure(hr, "Failed to allocate path to supported framework Install registry key."); + + hr = RegOpen(HKEY_LOCAL_MACHINE, sczFrameworkRegistryKey, KEY_READ, &hkFramework); + if (SUCCEEDED(hr)) + { + hr = RegReadNumber(hkFramework, L"Install", &dwFrameworkInstalled); + if (dwFrameworkInstalled) + { + hr = S_OK; + break; + } + } + + ReleaseNullObject(pNode); + } + + // If we looped through all the supported frameworks but didn't find anything, ensure we return a failure. + if (S_FALSE == hr) + { + hr = E_NOTFOUND; + ExitOnRootFailure(hr, "Failed to find a supported framework."); + } + + hr = UpdateSupportedRuntime(pixdManifest, pNode, &fUpdatedManifest); + ExitOnFailure(hr, "Failed to update supportedRuntime."); + } + // else no supported frameworks specified, so the startup/supportedRuntime must be enough. + + if (fUpdatedManifest) + { + hr = XmlSaveDocument(pixdManifest, wzConfigPath); + ExitOnFailure(hr, "Failed to save updated manifest over config file: %ls", wzConfigPath); + } + +LExit: + ReleaseRegKey(hkFramework); + ReleaseStr(sczFrameworkRegistryKey); + ReleaseStr(sczSupportedFrameworkVersion); + ReleaseObject(pNode); + ReleaseObject(pNodeList); + ReleaseObject(pixdManifest); + + XmlUninitialize(); + + return hr; +} + +// Fixes the supportedRuntime element if necessary. +static HRESULT UpdateSupportedRuntime( + __in IXMLDOMDocument* pixdManifest, + __in IXMLDOMNode* pixnSupportedFramework, + __out BOOL* pfUpdatedManifest + ) +{ + HRESULT hr = S_OK; + LPWSTR sczSupportedRuntimeVersion = NULL; + IXMLDOMNode* pixnStartup = NULL; + IXMLDOMNode* pixnSupportedRuntime = NULL; + + *pfUpdatedManifest = FALSE; + + // If the runtime version attribute is not specified, don't update the manifest. + hr = XmlGetAttributeEx(pixnSupportedFramework, L"runtimeVersion", &sczSupportedRuntimeVersion); + if (E_NOTFOUND == hr) + { + ExitFunction1(hr = S_OK); + } + ExitOnFailure(hr, "Failed to get supportedFramework/@runtimeVersion."); + + // Get the startup element. Fail if we can't find it since it'll be necessary to load the + // correct runtime. + hr = XmlSelectSingleNode(pixdManifest, L"/configuration/startup", &pixnStartup); + ExitOnFailure(hr, "Failed to get startup element."); + + if (S_FALSE == hr) + { + hr = E_NOTFOUND; + ExitOnRootFailure(hr, "Failed to find startup element in bootstrapper application config."); + } + + // Remove any pre-existing supported runtimes because they'll just get in the way and create our new one. + hr = XmlRemoveChildren(pixnStartup, L"supportedRuntime"); + ExitOnFailure(hr, "Failed to remove pre-existing supportedRuntime elements."); + + hr = XmlCreateChild(pixnStartup, L"supportedRuntime", &pixnSupportedRuntime); + ExitOnFailure(hr, "Failed to create supportedRuntime element."); + + hr = XmlSetAttribute(pixnSupportedRuntime, L"version", sczSupportedRuntimeVersion); + ExitOnFailure(hr, "Failed to set supportedRuntime/@version to '%ls'.", sczSupportedRuntimeVersion); + + *pfUpdatedManifest = TRUE; + +LExit: + ReleaseObject(pixnSupportedRuntime); + ReleaseObject(pixnStartup); + ReleaseStr(sczSupportedRuntimeVersion); + + return hr; +} + +// Gets the CLR host and caches it. +static HRESULT GetCLRHost( + __in LPCWSTR wzConfigPath, + __out ICorRuntimeHost **ppCLRHost + ) +{ + HRESULT hr = S_OK; + UINT uiMode = 0; + HMODULE hModule = NULL; + BOOL fFallbackToCorBindToCurrentRuntime = TRUE; + CLRCreateInstanceFnPtr pfnCLRCreateInstance = NULL; + ICLRMetaHostPolicy* pCLRMetaHostPolicy = NULL; + IStream* pCfgStream = NULL; + LPWSTR pwzVersion = NULL; + DWORD cchVersion = 0; + DWORD dwConfigFlags = 0; + ICLRRuntimeInfo* pCLRRuntimeInfo = NULL; + PFN_CORBINDTOCURRENTRUNTIME pfnCorBindToCurrentRuntime = NULL; + + // Always set the error mode because we will always restore it below. + uiMode = ::SetErrorMode(0); + + // Cache the CLR host to be shutdown later. This can occur on a different thread. + if (!vpCLRHost) + { + // Disable message boxes from being displayed on error and blocking execution. + ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS); + + hr = LoadSystemLibrary(L"mscoree.dll", &hModule); + ExitOnFailure(hr, "Failed to load mscoree.dll"); + + pfnCLRCreateInstance = reinterpret_cast(::GetProcAddress(hModule, "CLRCreateInstance")); + + if (pfnCLRCreateInstance) + { + hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast(&pCLRMetaHostPolicy)); + if (E_NOTIMPL != hr) + { + ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy."); + + fFallbackToCorBindToCurrentRuntime = FALSE; + } + } + + if (fFallbackToCorBindToCurrentRuntime) + { + pfnCorBindToCurrentRuntime = reinterpret_cast(::GetProcAddress(hModule, "CorBindToCurrentRuntime")); + ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime."); + + hr = pfnCorBindToCurrentRuntime(wzConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&vpCLRHost)); + ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path."); + } + else + { + + hr = SHCreateStreamOnFileEx(wzConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream); + ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", wzConfigPath); + + hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast(&pCLRRuntimeInfo)); + ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path."); + + // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL. + if (!cchVersion) + { + hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion); + if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr) + { + ExitOnFailure(hr, "Failed to get the length of the CLR version string."); + } + } + + hr = StrAlloc(&pwzVersion, cchVersion); + ExitOnFailure(hr, "Failed to allocate the CLR version string."); + + hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion); + ExitOnFailure(hr, "Failed to get the CLR version string."); + + if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion)) + { + hr = VerifyNET4RuntimeIsSupported(); + ExitOnFailure(hr, "Found unsupported .NET 4 Runtime."); + } + + if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags)) + { + hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime(); + ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime."); + } + + hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&vpCLRHost)); + ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost."); + + // TODO: use ICLRRuntimeHost instead of ICorRuntimeHost on .NET 4 since the former is faster and the latter is deprecated + //hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, reinterpret_cast(&pCLRRuntimeHost)); + //ExitOnRootFailure(hr, "Failed to get instance of ICLRRuntimeHost."); + } + } + + vpCLRHost->AddRef(); + *ppCLRHost = vpCLRHost; + +LExit: + ReleaseStr(pwzVersion); + ReleaseNullObject(pCLRRuntimeInfo); + ReleaseNullObject(pCfgStream); + ReleaseNullObject(pCLRMetaHostPolicy); + + // Unload the module so it's not in use when we install .NET. + if (FAILED(hr)) + { + ::FreeLibrary(hModule); + } + + ::SetErrorMode(uiMode); // restore the previous error mode. + + return hr; +} + +// Creates the bootstrapper app and returns it for the engine. +static HRESULT CreateManagedBootstrapperApplication( + __in _AppDomain* pAppDomain, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ) +{ + HRESULT hr = S_OK; + IBootstrapperApplicationFactory* pAppFactory = NULL; + IBootstrapperApplication* pApp = NULL; + + hr = CreateManagedBootstrapperApplicationFactory(pAppDomain, &pAppFactory); + ExitOnFailure(hr, "Failed to create the factory to create the bootstrapper application."); + + hr = pAppFactory->Create(pEngine, pArgs->pCommand, &pApp); + ExitOnFailure(hr, "Failed to create the bootstrapper application."); + + pResults->pfnBootstrapperApplicationProc = BalBaseBootstrapperApplicationProc; + pResults->pvBootstrapperApplicationProcContext = pApp; + pApp = NULL; + +LExit: + ReleaseNullObject(pApp); + ReleaseNullObject(pAppFactory); + + return hr; +} + +// Creates the app factory to create the managed app in the default AppDomain. +static HRESULT CreateManagedBootstrapperApplicationFactory( + __in _AppDomain* pAppDomain, + __out IBootstrapperApplicationFactory** ppAppFactory + ) +{ + HRESULT hr = S_OK; + BSTR bstrAssemblyName = NULL; + BSTR bstrTypeName = NULL; + _ObjectHandle* pObj = NULL; + VARIANT vtBAFactory; + + ::VariantInit(&vtBAFactory); + + bstrAssemblyName = ::SysAllocString(MBA_ASSEMBLY_FULL_NAME); + ExitOnNull(bstrAssemblyName, hr, E_OUTOFMEMORY, "Failed to allocate the full assembly name for the bootstrapper application factory."); + + bstrTypeName = ::SysAllocString(L"WixToolset.BootstrapperCore.BootstrapperApplicationFactory"); + ExitOnNull(bstrTypeName, hr, E_OUTOFMEMORY, "Failed to allocate the full type name for the BA factory."); + + hr = pAppDomain->CreateInstance(bstrAssemblyName, bstrTypeName, &pObj); + ExitOnRootFailure(hr, "Failed to create the BA factory object."); + + hr = pObj->Unwrap(&vtBAFactory); + ExitOnRootFailure(hr, "Failed to unwrap the BA factory object into the host domain."); + ExitOnNull(vtBAFactory.punkVal, hr, E_UNEXPECTED, "The variant did not contain the expected IUnknown pointer."); + + hr = vtBAFactory.punkVal->QueryInterface(__uuidof(IBootstrapperApplicationFactory), reinterpret_cast(ppAppFactory)); + ExitOnRootFailure(hr, "Failed to query for the bootstrapper app factory interface."); + +LExit: + ReleaseVariant(vtBAFactory); + ReleaseNullObject(pObj); + ReleaseBSTR(bstrTypeName); + ReleaseBSTR(bstrAssemblyName); + + return hr; +} + +static HRESULT CreatePrerequisiteBA( + __in HRESULT hrHostInitialization, + __in IBootstrapperEngine* pEngine, + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults + ) +{ + HRESULT hr = S_OK; + LPWSTR sczMbapreqPath = NULL; + HMODULE hModule = NULL; + + hr = PathRelativeToModule(&sczMbapreqPath, L"mbapreq.dll", vhInstance); + ExitOnFailure(hr, "Failed to get path to pre-requisite BA."); + + hModule = ::LoadLibraryW(sczMbapreqPath); + ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); + + PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast(::GetProcAddress(hModule, "MbaPrereqBootstrapperApplicationCreate")); + ExitOnNullWithLastError(pfnCreate, hr, "Failed to get MbaPrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath); + + hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); + ExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); + + vhMbapreqModule = hModule; + hModule = NULL; + +LExit: + if (hModule) + { + ::FreeLibrary(hModule); + } + ReleaseStr(sczMbapreqPath); + + return hr; +} + +static HRESULT VerifyNET4RuntimeIsSupported( + ) +{ + HRESULT hr = S_OK; + OS_VERSION osv = OS_VERSION_UNKNOWN; + DWORD dwServicePack = 0; + HKEY hKey = NULL; + DWORD er = ERROR_SUCCESS; + DWORD dwRelease = 0; + DWORD cchRelease = sizeof(dwRelease); + + OsGetVersion(&osv, &dwServicePack); + if (OS_VERSION_WIN7 == osv && 0 == dwServicePack) + { + hr = RegOpen(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full", KEY_QUERY_VALUE, &hKey); + if (E_FILENOTFOUND == hr) + { + ExitFunction1(hr = S_OK); + } + ExitOnFailure(hr, "Failed to open registry key for .NET 4."); + + er = ::RegQueryValueExW(hKey, L"Release", NULL, NULL, reinterpret_cast(&dwRelease), &cchRelease); + if (ERROR_FILE_NOT_FOUND == er) + { + ExitFunction1(hr = S_OK); + } + ExitOnWin32Error(er, hr, "Failed to get Release value."); + + if (NET452_RELEASE <= dwRelease) + { + hr = E_MBAHOST_NET452_ON_WIN7RTM; + } + } + +LExit: + ReleaseRegKey(hKey); + + return hr; +} diff --git a/src/mbahost/mbahost.def b/src/mbahost/mbahost.def new file mode 100644 index 00000000..4488df94 --- /dev/null +++ b/src/mbahost/mbahost.def @@ -0,0 +1,6 @@ +; Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + + +EXPORTS + BootstrapperApplicationCreate + BootstrapperApplicationDestroy diff --git a/src/mbahost/mbahost.vcxproj b/src/mbahost/mbahost.vcxproj new file mode 100644 index 00000000..d40333ab --- /dev/null +++ b/src/mbahost/mbahost.vcxproj @@ -0,0 +1,64 @@ + + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + + + {12C87C77-3547-44F8-8134-29BC915CB19D} + DynamicLibrary + v141 + Unicode + mbahost + mbahost.def + + + + + + + shlwapi.lib + + + + + + Create + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + diff --git a/src/mbahost/packages.config b/src/mbahost/packages.config new file mode 100644 index 00000000..41ba2f12 --- /dev/null +++ b/src/mbahost/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/mbahost/precomp.cpp b/src/mbahost/precomp.cpp new file mode 100644 index 00000000..37664a1c --- /dev/null +++ b/src/mbahost/precomp.cpp @@ -0,0 +1,3 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" diff --git a/src/wixext/BalBinder.cs b/src/wixext/BalBinder.cs deleted file mode 100644 index 30f7ab44..00000000 --- a/src/wixext/BalBinder.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.Extensions -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using WixToolset; - using WixToolset.Data; - using WixToolset.Data.Rows; - using WixToolset.Extensibility; - - public class BalBinder : BinderExtension - { - public override void Finish(Output output) - { - // Only process Bundles. - if (OutputType.Bundle != output.Type) - { - return; - } - - Table baTable = output.Tables["WixBootstrapperApplication"]; - Row baRow = baTable.Rows[0]; - string baId = (string)baRow[0]; - if (null == baId) - { - return; - } - - bool isStdBA = baId.StartsWith("WixStandardBootstrapperApplication"); - bool isMBA = baId.StartsWith("ManagedBootstrapperApplicationHost"); - - if (isStdBA || isMBA) - { - VerifyBAFunctions(output); - } - - if (isMBA) - { - VerifyPrereqPackages(output); - } - } - - private void VerifyBAFunctions(Output output) - { - Row baFunctionsRow = null; - Table baFunctionsTable = output.Tables["WixBalBAFunctions"]; - foreach (Row row in baFunctionsTable.RowsAs()) - { - if (null == baFunctionsRow) - { - baFunctionsRow = row; - } - else - { - this.Core.OnMessage(BalErrors.MultipleBAFunctions(row.SourceLineNumbers)); - } - } - - Table payloadPropertiesTable = output.Tables["WixPayloadProperties"]; - IEnumerable payloadPropertiesRows = payloadPropertiesTable.RowsAs(); - if (null == baFunctionsRow) - { - foreach (WixPayloadPropertiesRow payloadPropertiesRow in payloadPropertiesRows) - { - // TODO: Make core WiX canonicalize Name (this won't catch '.\bafunctions.dll'). - if (String.Equals(payloadPropertiesRow.Name, "bafunctions.dll", StringComparison.OrdinalIgnoreCase)) - { - this.Core.OnMessage(BalWarnings.UnmarkedBAFunctionsDLL(payloadPropertiesRow.SourceLineNumbers)); - } - } - } - else - { - // TODO: May need to revisit this depending on the outcome of #5273. - string payloadId = (string)baFunctionsRow[0]; - WixPayloadPropertiesRow bundlePayloadRow = payloadPropertiesRows.Single(x => payloadId == x.Id); - if (Compiler.BurnUXContainerId != bundlePayloadRow.Container) - { - this.Core.OnMessage(BalErrors.BAFunctionsPayloadRequiredInUXContainer(baFunctionsRow.SourceLineNumbers)); - } - } - } - - private void VerifyPrereqPackages(Output output) - { - Table prereqInfoTable = output.Tables["WixMbaPrereqInformation"]; - if (null == prereqInfoTable || prereqInfoTable.Rows.Count == 0) - { - this.Core.OnMessage(BalErrors.MissingPrereq()); - return; - } - - bool foundLicenseFile = false; - bool foundLicenseUrl = false; - - foreach (Row prereqInfoRow in prereqInfoTable.Rows) - { - if (null != prereqInfoRow[1]) - { - if (foundLicenseFile || foundLicenseUrl) - { - this.Core.OnMessage(BalErrors.MultiplePrereqLicenses(prereqInfoRow.SourceLineNumbers)); - return; - } - - foundLicenseFile = true; - } - - if (null != prereqInfoRow[2]) - { - if (foundLicenseFile || foundLicenseUrl) - { - this.Core.OnMessage(BalErrors.MultiplePrereqLicenses(prereqInfoRow.SourceLineNumbers)); - return; - } - - foundLicenseUrl = true; - } - } - } - } -} diff --git a/src/wixext/BalCompiler.cs b/src/wixext/BalCompiler.cs index 38ca9e3c..5b54ef58 100644 --- a/src/wixext/BalCompiler.cs +++ b/src/wixext/BalCompiler.cs @@ -1,21 +1,22 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Extensions +namespace WixToolset.Bal { using System; using System.Collections.Generic; using System.Xml.Linq; + using WixToolset.Bal.Tuples; using WixToolset.Data; - using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; using WixToolset.Extensibility; /// /// The compiler for the WiX Toolset Bal Extension. /// - public sealed class BalCompiler : CompilerExtension + public sealed class BalCompiler : BaseCompilerExtension { private SourceLineNumber addedConditionLineNumber; - private Dictionary prereqInfoRows; + private Dictionary prereqInfoRows; /// /// Instantiate a new BalCompiler. @@ -23,17 +24,20 @@ namespace WixToolset.Extensions public BalCompiler() { this.addedConditionLineNumber = null; - prereqInfoRows = new Dictionary(); - this.Namespace = "http://wixtoolset.org/schemas/v4/wxs/bal"; + this.prereqInfoRows = new Dictionary(); } + public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/bal"; + /// /// Processes an element for the Compiler. /// + /// + /// /// Parent element of element to process. /// Element to process. - /// Extra information about the context in which this element is being parsed. - public override void ParseElement(XElement parentElement, XElement element, IDictionary context) + /// Extra information about the context in which this element is being parsed. + public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) { switch (parentElement.Name.LocalName) { @@ -42,10 +46,10 @@ namespace WixToolset.Extensions switch (element.Name.LocalName) { case "Condition": - this.ParseConditionElement(element); + this.ParseConditionElement(intermediate, section, element); break; default: - this.Core.UnexpectedElement(parentElement, element); + this.ParseHelper.UnexpectedElement(parentElement, element); break; } break; @@ -53,18 +57,18 @@ namespace WixToolset.Extensions switch (element.Name.LocalName) { case "WixStandardBootstrapperApplication": - this.ParseWixStandardBootstrapperApplicationElement(element); + this.ParseWixStandardBootstrapperApplicationElement(intermediate, section, element); break; case "WixManagedBootstrapperApplicationHost": - this.ParseWixManagedBootstrapperApplicationHostElement(element); + this.ParseWixManagedBootstrapperApplicationHostElement(intermediate, section, element); break; default: - this.Core.UnexpectedElement(parentElement, element); + this.ParseHelper.UnexpectedElement(parentElement, element); break; } break; default: - this.Core.UnexpectedElement(parentElement, element); + this.ParseHelper.UnexpectedElement(parentElement, element); break; } } @@ -76,10 +80,10 @@ namespace WixToolset.Extensions /// Parent element of element to process. /// Attribute to process. /// Extra information about the context in which this element is being parsed. - public override void ParseAttribute(XElement parentElement, XAttribute attribute, IDictionary context) + public override void ParseAttribute(Intermediate intermediate, IntermediateSection section, XElement parentElement, XAttribute attribute, IDictionary context) { - SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(parentElement); - Row row; + SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(parentElement); + WixMbaPrereqInformationTuple prereqInfo; switch (parentElement.Name.LocalName) { @@ -90,7 +94,7 @@ namespace WixToolset.Extensions string packageId; if (!context.TryGetValue("PackageId", out packageId) || String.IsNullOrEmpty(packageId)) { - this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, parentElement.Name.LocalName, "Id", attribute.Name.LocalName)); + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, parentElement.Name.LocalName, "Id", attribute.Name.LocalName)); } else { @@ -98,80 +102,80 @@ namespace WixToolset.Extensions { case "PrereqLicenseFile": - if (!prereqInfoRows.TryGetValue(packageId, out row)) + if (!this.prereqInfoRows.TryGetValue(packageId, out prereqInfo)) { // at the time the extension attribute is parsed, the compiler might not yet have // parsed the PrereqPackage attribute, so we need to get it directly from the parent element. XAttribute prereqPackage = parentElement.Attribute(this.Namespace + "PrereqPackage"); - if (null != prereqPackage && YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, prereqPackage)) + if (null != prereqPackage && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, prereqPackage)) { - row = this.Core.CreateRow(sourceLineNumbers, "WixMbaPrereqInformation"); - row[0] = packageId; + prereqInfo = (WixMbaPrereqInformationTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixMbaPrereqInformation"); + prereqInfo.PackageId = packageId; - prereqInfoRows.Add(packageId, row); + this.prereqInfoRows.Add(packageId, prereqInfo); } else { - this.Core.OnMessage(BalErrors.AttributeRequiresPrereqPackage(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseFile")); + this.Messaging.Write(BalErrors.AttributeRequiresPrereqPackage(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseFile")); break; } } - if (null != row[2]) + if (null != prereqInfo.LicenseUrl) { - this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseFile", "PrereqLicenseUrl")); + this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseFile", "PrereqLicenseUrl")); } else { - row[1] = this.Core.GetAttributeValue(sourceLineNumbers, attribute); + prereqInfo.LicenseFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute); } break; case "PrereqLicenseUrl": - if (!prereqInfoRows.TryGetValue(packageId, out row)) + if (!this.prereqInfoRows.TryGetValue(packageId, out prereqInfo)) { // at the time the extension attribute is parsed, the compiler might not yet have // parsed the PrereqPackage attribute, so we need to get it directly from the parent element. XAttribute prereqPackage = parentElement.Attribute(this.Namespace + "PrereqPackage"); - if (null != prereqPackage && YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, prereqPackage)) + if (null != prereqPackage && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, prereqPackage)) { - row = this.Core.CreateRow(sourceLineNumbers, "WixMbaPrereqInformation"); - row[0] = packageId; + prereqInfo = (WixMbaPrereqInformationTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixMbaPrereqInformation"); + prereqInfo.PackageId = packageId; - prereqInfoRows.Add(packageId, row); + this.prereqInfoRows.Add(packageId, prereqInfo); } else { - this.Core.OnMessage(BalErrors.AttributeRequiresPrereqPackage(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseUrl")); + this.Messaging.Write(BalErrors.AttributeRequiresPrereqPackage(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseUrl")); break; } } - if (null != row[1]) + if (null != prereqInfo.LicenseFile) { - this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseUrl", "PrereqLicenseFile")); + this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseUrl", "PrereqLicenseFile")); } else { - row[2] = this.Core.GetAttributeValue(sourceLineNumbers, attribute); + prereqInfo.LicenseUrl = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute); } break; case "PrereqPackage": - if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attribute)) + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attribute)) { - if (!prereqInfoRows.TryGetValue(packageId, out row)) + if (!this.prereqInfoRows.TryGetValue(packageId, out prereqInfo)) { - row = this.Core.CreateRow(sourceLineNumbers, "WixMbaPrereqInformation"); - row[0] = packageId; + prereqInfo = (WixMbaPrereqInformationTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixMbaPrereqInformation"); + prereqInfo.PackageId = packageId; - prereqInfoRows.Add(packageId, row); + this.prereqInfoRows.Add(packageId, prereqInfo); } } break; default: - this.Core.UnexpectedAttribute(parentElement, attribute); + this.ParseHelper.UnexpectedAttribute(parentElement, attribute); break; } } @@ -180,21 +184,21 @@ namespace WixToolset.Extensions string payloadId; if (!context.TryGetValue("Id", out payloadId) || String.IsNullOrEmpty(payloadId)) { - this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, parentElement.Name.LocalName, "Id", attribute.Name.LocalName)); + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, parentElement.Name.LocalName, "Id", attribute.Name.LocalName)); } else { switch (attribute.Name.LocalName) { case "BAFunctions": - if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attribute)) + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attribute)) { - row = this.Core.CreateRow(sourceLineNumbers, "WixBalBAFunctions"); - row[0] = payloadId; + var tuple = (WixBalBAFunctionsTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixBalBAFunctions"); + tuple.PayloadId = payloadId; } break; default: - this.Core.UnexpectedAttribute(parentElement, attribute); + this.ParseHelper.UnexpectedAttribute(parentElement, attribute); break; } } @@ -205,21 +209,21 @@ namespace WixToolset.Extensions XAttribute variableName = parentElement.Attribute("Name"); if (null == variableName) { - this.Core.OnMessage(WixErrors.ExpectedParentWithAttribute(sourceLineNumbers, "Variable", "Overridable", "Name")); + this.Messaging.Write(ErrorMessages.ExpectedParentWithAttribute(sourceLineNumbers, "Variable", "Overridable", "Name")); } else { switch (attribute.Name.LocalName) { case "Overridable": - if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attribute)) + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attribute)) { - row = this.Core.CreateRow(sourceLineNumbers, "WixStdbaOverridableVariable"); - row[0] = variableName; + var tuple = (WixStdbaOverridableVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixStdbaOverridableVariable"); + tuple.Name = variableName.Value; } break; default: - this.Core.UnexpectedAttribute(parentElement, attribute); + this.ParseHelper.UnexpectedAttribute(parentElement, attribute); break; } } @@ -231,10 +235,10 @@ namespace WixToolset.Extensions /// Parses a Condition element for Bundles. /// /// The element to parse. - private void ParseConditionElement(XElement node) + private void ParseConditionElement(Intermediate intermediate, IntermediateSection section, XElement node) { - SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string condition = this.Core.GetConditionInnerText(node); // condition is the inner text of the element. + SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); + string condition = this.ParseHelper.GetConditionInnerText(node); // condition is the inner text of the element. string message = null; foreach (XAttribute attrib in node.Attributes()) @@ -244,37 +248,37 @@ namespace WixToolset.Extensions switch (attrib.Name.LocalName) { case "Message": - message = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + message = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; default: - this.Core.UnexpectedAttribute(node, attrib); + this.ParseHelper.UnexpectedAttribute(node, attrib); break; } } else { - this.Core.ParseExtensionAttribute(node, attrib); + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); } } - this.Core.ParseForExtensionElements(node); + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); // Error check the values. if (String.IsNullOrEmpty(condition)) { - this.Core.OnMessage(WixErrors.ConditionExpected(sourceLineNumbers, node.Name.LocalName)); + this.Messaging.Write(ErrorMessages.ConditionExpected(sourceLineNumbers, node.Name.LocalName)); } if (null == message) { - this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Message")); + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Message")); } - if (!this.Core.EncounteredError) + if (!this.Messaging.EncounteredError) { - Row row = this.Core.CreateRow(sourceLineNumbers, "WixBalCondition"); - row[0] = condition; - row[1] = message; + var tuple = (WixBalConditionTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixBalCondition"); + tuple.Condition = condition; + tuple.Message = message; if (null == this.addedConditionLineNumber) { @@ -287,9 +291,9 @@ namespace WixToolset.Extensions /// Parses a WixStandardBootstrapperApplication element for Bundles. /// /// The element to parse. - private void ParseWixStandardBootstrapperApplicationElement(XElement node) + private void ParseWixStandardBootstrapperApplicationElement(Intermediate intermediate, IntermediateSection section, XElement node) { - SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); string launchTarget = null; string launchTargetElevatedId = null; string launchArguments = null; @@ -314,101 +318,101 @@ namespace WixToolset.Extensions switch (attrib.Name.LocalName) { case "LaunchTarget": - launchTarget = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + launchTarget = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "LaunchTargetElevatedId": - launchTargetElevatedId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + launchTargetElevatedId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); break; case "LaunchArguments": - launchArguments = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + launchArguments = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "LaunchHidden": - launchHidden = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + launchHidden = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "LaunchWorkingFolder": - launchWorkingDir = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + launchWorkingDir = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "LicenseFile": - licenseFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + licenseFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "LicenseUrl": - licenseUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.CanBeEmpty); + licenseUrl = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.CanBeEmpty); break; case "LogoFile": - logoFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + logoFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "LogoSideFile": - logoSideFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + logoSideFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "ThemeFile": - themeFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + themeFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "LocalizationFile": - localizationFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + localizationFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "SuppressOptionsUI": - suppressOptionsUI = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + suppressOptionsUI = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressDowngradeFailure": - suppressDowngradeFailure = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + suppressDowngradeFailure = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SuppressRepair": - suppressRepair = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + suppressRepair = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ShowVersion": - showVersion = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + showVersion = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "SupportCacheOnly": - supportCacheOnly = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + supportCacheOnly = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; default: - this.Core.UnexpectedAttribute(node, attrib); + this.ParseHelper.UnexpectedAttribute(node, attrib); break; } } else { - this.Core.ParseExtensionAttribute(node, attrib); + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); } } - this.Core.ParseForExtensionElements(node); + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); if (String.IsNullOrEmpty(licenseFile) && null == licenseUrl) { - this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "LicenseFile", "LicenseUrl", true)); + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "LicenseFile", "LicenseUrl", true)); } - if (!this.Core.EncounteredError) + if (!this.Messaging.EncounteredError) { if (!String.IsNullOrEmpty(launchTarget)) { - WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixBundleVariable"); - row.Id = "LaunchTarget"; + var row = (WixBundleVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixBundleVariable"); + row.Id = new Identifier("LaunchTarget", AccessModifier.Public); row.Value = launchTarget; row.Type = "string"; } if (!String.IsNullOrEmpty(launchTargetElevatedId)) { - WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixBundleVariable"); - row.Id = "LaunchTargetElevatedId"; + var row = (WixBundleVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixBundleVariable"); + row.Id = new Identifier("LaunchTargetElevatedId", AccessModifier.Public); row.Value = launchTargetElevatedId; row.Type = "string"; } if (!String.IsNullOrEmpty(launchArguments)) { - WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixBundleVariable"); - row.Id = "LaunchArguments"; + var row = (WixBundleVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixBundleVariable"); + row.Id = new Identifier("LaunchArguments", AccessModifier.Public); row.Value = launchArguments; row.Type = "string"; } if (YesNoType.Yes == launchHidden) { - WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixBundleVariable"); - row.Id = "LaunchHidden"; + var row = (WixBundleVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixBundleVariable"); + row.Id = new Identifier("LaunchHidden", AccessModifier.Public); row.Value = "yes"; row.Type = "string"; } @@ -416,80 +420,80 @@ namespace WixToolset.Extensions if (!String.IsNullOrEmpty(launchWorkingDir)) { - WixBundleVariableRow row = (WixBundleVariableRow)this.Core.CreateRow(sourceLineNumbers, "Variable"); - row.Id = "LaunchWorkingFolder"; + var row = (WixBundleVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "Variable"); + row.Id = new Identifier("LaunchWorkingFolder", AccessModifier.Public); row.Value = launchWorkingDir; row.Type = "string"; } if (!String.IsNullOrEmpty(licenseFile)) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "WixStdbaLicenseRtf"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("WixStdbaLicenseRtf", AccessModifier.Public); wixVariableRow.Value = licenseFile; } if (null != licenseUrl) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "WixStdbaLicenseUrl"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("WixStdbaLicenseUrl", AccessModifier.Public); wixVariableRow.Value = licenseUrl; } if (!String.IsNullOrEmpty(logoFile)) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "WixStdbaLogo"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("WixStdbaLogo", AccessModifier.Public); wixVariableRow.Value = logoFile; } if (!String.IsNullOrEmpty(logoSideFile)) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "WixStdbaLogoSide"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("WixStdbaLogoSide", AccessModifier.Public); wixVariableRow.Value = logoSideFile; } if (!String.IsNullOrEmpty(themeFile)) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "WixStdbaThemeXml"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("WixStdbaThemeXml", AccessModifier.Public); wixVariableRow.Value = themeFile; } if (!String.IsNullOrEmpty(localizationFile)) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "WixStdbaThemeWxl"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("WixStdbaThemeWxl", AccessModifier.Public); wixVariableRow.Value = localizationFile; } if (YesNoType.Yes == suppressOptionsUI || YesNoType.Yes == suppressDowngradeFailure || YesNoType.Yes == suppressRepair || YesNoType.Yes == showVersion || YesNoType.Yes == supportCacheOnly) { - Row row = this.Core.CreateRow(sourceLineNumbers, "WixStdbaOptions"); + var tuple = (WixStdbaOptionsTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixStdbaOptions"); if (YesNoType.Yes == suppressOptionsUI) { - row[0] = 1; + tuple.SuppressOptionsUI = 1; } if (YesNoType.Yes == suppressDowngradeFailure) { - row[1] = 1; + tuple.SuppressDowngradeFailure = 1; } if (YesNoType.Yes == suppressRepair) { - row[2] = 1; + tuple.SuppressRepair = 1; } if (YesNoType.Yes == showVersion) { - row[3] = 1; + tuple.ShowVersion = 1; } if (YesNoType.Yes == supportCacheOnly) { - row[4] = 1; + tuple.SupportCacheOnly = 1; } } } @@ -499,9 +503,9 @@ namespace WixToolset.Extensions /// Parses a WixManagedBootstrapperApplicationHost element for Bundles. /// /// The element to parse. - private void ParseWixManagedBootstrapperApplicationHostElement(XElement node) + private void ParseWixManagedBootstrapperApplicationHostElement(Intermediate intermediate, IntermediateSection section, XElement node) { - SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node); string logoFile = null; string themeFile = null; string localizationFile = null; @@ -513,47 +517,47 @@ namespace WixToolset.Extensions switch (attrib.Name.LocalName) { case "LogoFile": - logoFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + logoFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "ThemeFile": - themeFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + themeFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; case "LocalizationFile": - localizationFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + localizationFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); break; default: - this.Core.UnexpectedAttribute(node, attrib); + this.ParseHelper.UnexpectedAttribute(node, attrib); break; } } else { - this.Core.ParseExtensionAttribute(node, attrib); + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib); } } - this.Core.ParseForExtensionElements(node); + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node); - if (!this.Core.EncounteredError) + if (!this.Messaging.EncounteredError) { if (!String.IsNullOrEmpty(logoFile)) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "PreqbaLogo"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("PreqbaLogo", AccessModifier.Public); wixVariableRow.Value = logoFile; } if (!String.IsNullOrEmpty(themeFile)) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "PreqbaThemeXml"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("PreqbaThemeXml", AccessModifier.Public); wixVariableRow.Value = themeFile; } if (!String.IsNullOrEmpty(localizationFile)) { - WixVariableRow wixVariableRow = (WixVariableRow)this.Core.CreateRow(sourceLineNumbers, "WixVariable"); - wixVariableRow.Id = "PreqbaThemeWxl"; + var wixVariableRow = (WixVariableTuple)this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixVariable"); + wixVariableRow.Id = new Identifier("PreqbaThemeWxl", AccessModifier.Public); wixVariableRow.Value = localizationFile; } } diff --git a/src/wixext/BalErrors.cs b/src/wixext/BalErrors.cs new file mode 100644 index 00000000..5591ae1d --- /dev/null +++ b/src/wixext/BalErrors.cs @@ -0,0 +1,55 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using System; + using System.Resources; + using WixToolset.Data; + + public static class BalErrors + { + public static Message AttributeRequiresPrereqPackage(SourceLineNumber sourceLineNumbers, string elementName, string attributeName) + { + return Message(sourceLineNumbers, Ids.AttributeRequiresPrereqPackage, "When the {0}/@{1} attribute is specified, the {0}/@PrereqPackage attribute must be set to \"yes\".", elementName, attributeName); + } + + public static Message BAFunctionsPayloadRequiredInUXContainer(SourceLineNumber sourceLineNumbers) + { + return Message(sourceLineNumbers, Ids.BAFunctionsPayloadRequiredInUXContainer, "The BAFunctions DLL Payload element must be located inside the BootstrapperApplication container."); + } + + public static Message MissingPrereq() + { + return Message(null, Ids.MissingPrereq, "There must be at least one PrereqPackage when using the ManagedBootstrapperApplicationHost.\nThis is typically done by using the WixNetFxExtension and referencing one of the NetFxAsPrereq package groups."); + } + + public static Message MultipleBAFunctions(SourceLineNumber sourceLineNumbers) + { + return Message(sourceLineNumbers, Ids.MultipleBAFunctions, "WixStandardBootstrapperApplication doesn't support multiple BAFunctions DLLs."); + } + + public static Message MultiplePrereqLicenses(SourceLineNumber sourceLineNumbers) + { + return Message(sourceLineNumbers, Ids.MultiplePrereqLicenses, "There may only be one package in the bundle that has either the PrereqLicenseFile attribute or the PrereqLicenseUrl attribute."); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args); + } + + public enum Ids + { + AttributeRequiresPrereqPackage = 6801, + MissingPrereq = 6802, + MultiplePrereqLicenses = 6803, + MultipleBAFunctions = 6804, + BAFunctionsPayloadRequiredInUXContainer = 6805, + } + } +} diff --git a/src/wixext/BalExtensionData.cs b/src/wixext/BalExtensionData.cs index 7e8dea5b..46152b53 100644 --- a/src/wixext/BalExtensionData.cs +++ b/src/wixext/BalExtensionData.cs @@ -1,55 +1,30 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -namespace WixToolset.Extensions +namespace WixToolset.Bal { - using System; - using System.Reflection; using WixToolset.Data; using WixToolset.Extensibility; /// /// The WiX Toolset Bal Extension. /// - public sealed class BalExtensionData : ExtensionData + public sealed class BalExtensionData : BaseExtensionData { /// - /// Gets the optional table definitions for this extension. + /// Gets the default culture. /// - /// The optional table definitions for this extension. - public override TableDefinitionCollection TableDefinitions - { - get - { - return BalExtensionData.GetExtensionTableDefinitions(); - } - } + /// The default culture. + public override string DefaultCulture => "en-US"; - /// - /// Gets the library associated with this extension. - /// - /// The table definitions to use while loading the library. - /// The loaded library. - public override Library GetLibrary(TableDefinitionCollection tableDefinitions) + public override bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition) { - return BalExtensionData.GetExtensionLibrary(tableDefinitions); + tupleDefinition = BalTupleDefinitions.ByName(name); + return tupleDefinition != null; } - /// - /// Internal mechanism to access the extension's table definitions. - /// - /// Extension's table definitions. - internal static TableDefinitionCollection GetExtensionTableDefinitions() - { - return ExtensionData.LoadTableDefinitionHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.tables.xml"); - } - - /// - /// Internal mechanism to access the extension's library. - /// - /// Extension's library. - internal static Library GetExtensionLibrary(TableDefinitionCollection tableDefinitions) + public override Intermediate GetLibrary(ITupleDefinitionCreator tupleDefinitions) { - return ExtensionData.LoadLibraryHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.bal.wixlib", tableDefinitions); + return Intermediate.Load(typeof(BalExtensionData).Assembly, "WixToolset.Bal.bal.wixlib", tupleDefinitions); } } } diff --git a/src/wixext/BalExtensionFactory.cs b/src/wixext/BalExtensionFactory.cs new file mode 100644 index 00000000..936686a6 --- /dev/null +++ b/src/wixext/BalExtensionFactory.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using System; + using System.Collections.Generic; + using WixToolset.Extensibility; + + public class BalExtensionFactory : BaseExtensionFactory + { + protected override IEnumerable ExtensionTypes => new[] + { + typeof(BalCompiler), + typeof(BalExtensionData), + typeof(BalWindowsInstallerBackendBinderExtension), + }; + } +} diff --git a/src/wixext/BalWarnings.cs b/src/wixext/BalWarnings.cs new file mode 100644 index 00000000..18b25062 --- /dev/null +++ b/src/wixext/BalWarnings.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using System; + using System.Resources; + using WixToolset.Data; + + public static class BalWarnings + { + public static Message UnmarkedBAFunctionsDLL(SourceLineNumber sourceLineNumbers) + { + return Message(sourceLineNumbers, Ids.UnmarkedBAFunctionsDLL, "WixStandardBootstrapperApplication doesn't automatically load BAFunctions.dll. Use the bal:BAFunctions attribute to indicate that it should be loaded."); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, format, args); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Warning, (int)id, resourceManager, resourceName, args); + } + + public enum Ids + { + UnmarkedBAFunctionsDLL = 6501, + } + } +} diff --git a/src/wixext/BalWindowsInstallerBackendBinderExtension.cs b/src/wixext/BalWindowsInstallerBackendBinderExtension.cs new file mode 100644 index 00000000..fbda9d1b --- /dev/null +++ b/src/wixext/BalWindowsInstallerBackendBinderExtension.cs @@ -0,0 +1,146 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using System; + using System.Linq; + using System.Xml; + using WixToolset.Data; + using WixToolset.Data.WindowsInstaller; + using WixToolset.Data.WindowsInstaller.Rows; + using WixToolset.Extensibility; + using WixToolset.Extensibility.Data; + + public class BalWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension + { + // TODO: don't duplicate this from WixToolset.Core.Compiler + public const string BurnUXContainerId = "WixUXContainer"; + + private static readonly TableDefinition[] Tables = LoadTables(); + + protected override TableDefinition[] TableDefinitionsForTuples => Tables; + + private static TableDefinition[] LoadTables() + { + using (var resourceStream = typeof(BalWindowsInstallerBackendBinderExtension).Assembly.GetManifestResourceStream("WixToolset.Bal.tables.xml")) + using (var reader = XmlReader.Create(resourceStream)) + { + var tables = TableDefinitionCollection.Load(reader); + return tables.ToArray(); + } + } + + public override void PostBackendBind(BindResult result, Pdb pdb) + { + base.PostBackendBind(result, pdb); + + var output = pdb.Output; + + // Only process Bundles. + if (OutputType.Bundle != output.Type) + { + return; + } + + var baTable = output.Tables["WixBootstrapperApplication"]; + var baRow = baTable.Rows[0]; + var baId = (string)baRow[0]; + if (null == baId) + { + return; + } + + var isStdBA = baId.StartsWith("WixStandardBootstrapperApplication"); + var isMBA = baId.StartsWith("ManagedBootstrapperApplicationHost"); + + if (isStdBA || isMBA) + { + this.VerifyBAFunctions(output); + } + + if (isMBA) + { + this.VerifyPrereqPackages(output); + } + } + + private void VerifyBAFunctions(Output output) + { + Row baFunctionsRow = null; + var baFunctionsTable = output.Tables["WixBalBAFunctions"]; + foreach (var row in baFunctionsTable.Rows) + { + if (null == baFunctionsRow) + { + baFunctionsRow = row; + } + else + { + this.Messaging.Write(BalErrors.MultipleBAFunctions(row.SourceLineNumbers)); + } + } + + var payloadPropertiesTable = output.Tables["WixPayloadProperties"]; + var payloadPropertiesRows = payloadPropertiesTable.Rows.Cast(); + if (null == baFunctionsRow) + { + foreach (var payloadPropertiesRow in payloadPropertiesRows) + { + // TODO: Make core WiX canonicalize Name (this won't catch '.\bafunctions.dll'). + if (string.Equals(payloadPropertiesRow.Name, "bafunctions.dll", StringComparison.OrdinalIgnoreCase)) + { + this.Messaging.Write(BalWarnings.UnmarkedBAFunctionsDLL(payloadPropertiesRow.SourceLineNumbers)); + } + } + } + else + { + // TODO: May need to revisit this depending on the outcome of #5273. + var payloadId = (string)baFunctionsRow[0]; + var bundlePayloadRow = payloadPropertiesRows.Single(x => payloadId == x.Id); + if (BurnUXContainerId != bundlePayloadRow.Container) + { + this.Messaging.Write(BalErrors.BAFunctionsPayloadRequiredInUXContainer(baFunctionsRow.SourceLineNumbers)); + } + } + } + + private void VerifyPrereqPackages(Output output) + { + var prereqInfoTable = output.Tables["WixMbaPrereqInformation"]; + if (null == prereqInfoTable || prereqInfoTable.Rows.Count == 0) + { + this.Messaging.Write(BalErrors.MissingPrereq()); + return; + } + + var foundLicenseFile = false; + var foundLicenseUrl = false; + + foreach (Row prereqInfoRow in prereqInfoTable.Rows) + { + if (null != prereqInfoRow[1]) + { + if (foundLicenseFile || foundLicenseUrl) + { + this.Messaging.Write(BalErrors.MultiplePrereqLicenses(prereqInfoRow.SourceLineNumbers)); + return; + } + + foundLicenseFile = true; + } + + if (null != prereqInfoRow[2]) + { + if (foundLicenseFile || foundLicenseUrl) + { + this.Messaging.Write(BalErrors.MultiplePrereqLicenses(prereqInfoRow.SourceLineNumbers)); + return; + } + + foundLicenseUrl = true; + } + } + } + } +} diff --git a/src/wixext/Tuples/BalTupleDefinitions.cs b/src/wixext/Tuples/BalTupleDefinitions.cs new file mode 100644 index 00000000..676db9f6 --- /dev/null +++ b/src/wixext/Tuples/BalTupleDefinitions.cs @@ -0,0 +1,55 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using System; + using WixToolset.Data; + + public enum BalTupleDefinitionType + { + WixBalBAFunctions, + WixBalCondition, + WixMbaPrereqInformation, + WixStdbaOptions, + WixStdbaOverridableVariable, + } + + public static partial class BalTupleDefinitions + { + public static readonly Version Version = new Version("4.0.0"); + + public static IntermediateTupleDefinition ByName(string name) + { + if (!Enum.TryParse(name, out BalTupleDefinitionType type)) + { + return null; + } + + return ByType(type); + } + + public static IntermediateTupleDefinition ByType(BalTupleDefinitionType type) + { + switch (type) + { + case BalTupleDefinitionType.WixBalBAFunctions: + return BalTupleDefinitions.WixBalBAFunctions; + + case BalTupleDefinitionType.WixBalCondition: + return BalTupleDefinitions.WixBalCondition; + + case BalTupleDefinitionType.WixMbaPrereqInformation: + return BalTupleDefinitions.WixMbaPrereqInformation; + + case BalTupleDefinitionType.WixStdbaOptions: + return BalTupleDefinitions.WixStdbaOptions; + + case BalTupleDefinitionType.WixStdbaOverridableVariable: + return BalTupleDefinitions.WixStdbaOverridableVariable; + + default: + throw new ArgumentOutOfRangeException(nameof(type)); + } + } + } +} diff --git a/src/wixext/Tuples/WixBalBAFunctionsTuple.cs b/src/wixext/Tuples/WixBalBAFunctionsTuple.cs new file mode 100644 index 00000000..f753f239 --- /dev/null +++ b/src/wixext/Tuples/WixBalBAFunctionsTuple.cs @@ -0,0 +1,47 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using WixToolset.Data; + using WixToolset.Bal.Tuples; + + public static partial class BalTupleDefinitions + { + public static readonly IntermediateTupleDefinition WixBalBAFunctions = new IntermediateTupleDefinition( + BalTupleDefinitionType.WixBalBAFunctions.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixBalBAFunctionsTupleFields.PayloadId), IntermediateFieldType.String), + }, + typeof(WixBalBAFunctionsTuple)); + } +} + +namespace WixToolset.Bal.Tuples +{ + using WixToolset.Data; + + public enum WixBalBAFunctionsTupleFields + { + PayloadId, + } + + public class WixBalBAFunctionsTuple : IntermediateTuple + { + public WixBalBAFunctionsTuple() : base(BalTupleDefinitions.WixBalBAFunctions, null, null) + { + } + + public WixBalBAFunctionsTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(BalTupleDefinitions.WixBalBAFunctions, sourceLineNumber, id) + { + } + + public IntermediateField this[WixBalBAFunctionsTupleFields index] => this.Fields[(int)index]; + + public string PayloadId + { + get => this.Fields[(int)WixBalBAFunctionsTupleFields.PayloadId].AsString(); + set => this.Set((int)WixBalBAFunctionsTupleFields.PayloadId, value); + } + } +} \ No newline at end of file diff --git a/src/wixext/Tuples/WixBalConditionTuple.cs b/src/wixext/Tuples/WixBalConditionTuple.cs new file mode 100644 index 00000000..4c0ddd1d --- /dev/null +++ b/src/wixext/Tuples/WixBalConditionTuple.cs @@ -0,0 +1,55 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using WixToolset.Data; + using WixToolset.Bal.Tuples; + + public static partial class BalTupleDefinitions + { + public static readonly IntermediateTupleDefinition WixBalCondition = new IntermediateTupleDefinition( + BalTupleDefinitionType.WixBalCondition.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixBalConditionTupleFields.Condition), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixBalConditionTupleFields.Message), IntermediateFieldType.String), + }, + typeof(WixBalConditionTuple)); + } +} + +namespace WixToolset.Bal.Tuples +{ + using WixToolset.Data; + + public enum WixBalConditionTupleFields + { + Condition, + Message, + } + + public class WixBalConditionTuple : IntermediateTuple + { + public WixBalConditionTuple() : base(BalTupleDefinitions.WixBalCondition, null, null) + { + } + + public WixBalConditionTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(BalTupleDefinitions.WixBalCondition, sourceLineNumber, id) + { + } + + public IntermediateField this[WixBalConditionTupleFields index] => this.Fields[(int)index]; + + public string Condition + { + get => this.Fields[(int)WixBalConditionTupleFields.Condition].AsString(); + set => this.Set((int)WixBalConditionTupleFields.Condition, value); + } + + public string Message + { + get => this.Fields[(int)WixBalConditionTupleFields.Message].AsString(); + set => this.Set((int)WixBalConditionTupleFields.Message, value); + } + } +} \ No newline at end of file diff --git a/src/wixext/Tuples/WixMbaPrereqInformationTuple.cs b/src/wixext/Tuples/WixMbaPrereqInformationTuple.cs new file mode 100644 index 00000000..bcbe9f84 --- /dev/null +++ b/src/wixext/Tuples/WixMbaPrereqInformationTuple.cs @@ -0,0 +1,63 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using WixToolset.Data; + using WixToolset.Bal.Tuples; + + public static partial class BalTupleDefinitions + { + public static readonly IntermediateTupleDefinition WixMbaPrereqInformation = new IntermediateTupleDefinition( + BalTupleDefinitionType.WixMbaPrereqInformation.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixMbaPrereqInformationTupleFields.PackageId), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixMbaPrereqInformationTupleFields.LicenseFile), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixMbaPrereqInformationTupleFields.LicenseUrl), IntermediateFieldType.String), + }, + typeof(WixMbaPrereqInformationTuple)); + } +} + +namespace WixToolset.Bal.Tuples +{ + using WixToolset.Data; + + public enum WixMbaPrereqInformationTupleFields + { + PackageId, + LicenseFile, + LicenseUrl, + } + + public class WixMbaPrereqInformationTuple : IntermediateTuple + { + public WixMbaPrereqInformationTuple() : base(BalTupleDefinitions.WixMbaPrereqInformation, null, null) + { + } + + public WixMbaPrereqInformationTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(BalTupleDefinitions.WixMbaPrereqInformation, sourceLineNumber, id) + { + } + + public IntermediateField this[WixMbaPrereqInformationTupleFields index] => this.Fields[(int)index]; + + public string PackageId + { + get => this.Fields[(int)WixMbaPrereqInformationTupleFields.PackageId].AsString(); + set => this.Set((int)WixMbaPrereqInformationTupleFields.PackageId, value); + } + + public string LicenseFile + { + get => this.Fields[(int)WixMbaPrereqInformationTupleFields.LicenseFile].AsString(); + set => this.Set((int)WixMbaPrereqInformationTupleFields.LicenseFile, value); + } + + public string LicenseUrl + { + get => this.Fields[(int)WixMbaPrereqInformationTupleFields.LicenseUrl].AsString(); + set => this.Set((int)WixMbaPrereqInformationTupleFields.LicenseUrl, value); + } + } +} \ No newline at end of file diff --git a/src/wixext/Tuples/WixStdbaOptionsTuple.cs b/src/wixext/Tuples/WixStdbaOptionsTuple.cs new file mode 100644 index 00000000..d930eb47 --- /dev/null +++ b/src/wixext/Tuples/WixStdbaOptionsTuple.cs @@ -0,0 +1,79 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using WixToolset.Data; + using WixToolset.Bal.Tuples; + + public static partial class BalTupleDefinitions + { + public static readonly IntermediateTupleDefinition WixStdbaOptions = new IntermediateTupleDefinition( + BalTupleDefinitionType.WixStdbaOptions.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixStdbaOptionsTupleFields.SuppressOptionsUI), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixStdbaOptionsTupleFields.SuppressDowngradeFailure), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixStdbaOptionsTupleFields.SuppressRepair), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixStdbaOptionsTupleFields.ShowVersion), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixStdbaOptionsTupleFields.SupportCacheOnly), IntermediateFieldType.Number), + }, + typeof(WixStdbaOptionsTuple)); + } +} + +namespace WixToolset.Bal.Tuples +{ + using WixToolset.Data; + + public enum WixStdbaOptionsTupleFields + { + SuppressOptionsUI, + SuppressDowngradeFailure, + SuppressRepair, + ShowVersion, + SupportCacheOnly, + } + + public class WixStdbaOptionsTuple : IntermediateTuple + { + public WixStdbaOptionsTuple() : base(BalTupleDefinitions.WixStdbaOptions, null, null) + { + } + + public WixStdbaOptionsTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(BalTupleDefinitions.WixStdbaOptions, sourceLineNumber, id) + { + } + + public IntermediateField this[WixStdbaOptionsTupleFields index] => this.Fields[(int)index]; + + public int SuppressOptionsUI + { + get => this.Fields[(int)WixStdbaOptionsTupleFields.SuppressOptionsUI].AsNumber(); + set => this.Set((int)WixStdbaOptionsTupleFields.SuppressOptionsUI, value); + } + + public int SuppressDowngradeFailure + { + get => this.Fields[(int)WixStdbaOptionsTupleFields.SuppressDowngradeFailure].AsNumber(); + set => this.Set((int)WixStdbaOptionsTupleFields.SuppressDowngradeFailure, value); + } + + public int SuppressRepair + { + get => this.Fields[(int)WixStdbaOptionsTupleFields.SuppressRepair].AsNumber(); + set => this.Set((int)WixStdbaOptionsTupleFields.SuppressRepair, value); + } + + public int ShowVersion + { + get => this.Fields[(int)WixStdbaOptionsTupleFields.ShowVersion].AsNumber(); + set => this.Set((int)WixStdbaOptionsTupleFields.ShowVersion, value); + } + + public int SupportCacheOnly + { + get => this.Fields[(int)WixStdbaOptionsTupleFields.SupportCacheOnly].AsNumber(); + set => this.Set((int)WixStdbaOptionsTupleFields.SupportCacheOnly, value); + } + } +} \ No newline at end of file diff --git a/src/wixext/Tuples/WixStdbaOverridableVariableTuple.cs b/src/wixext/Tuples/WixStdbaOverridableVariableTuple.cs new file mode 100644 index 00000000..3ba982ea --- /dev/null +++ b/src/wixext/Tuples/WixStdbaOverridableVariableTuple.cs @@ -0,0 +1,47 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Bal +{ + using WixToolset.Data; + using WixToolset.Bal.Tuples; + + public static partial class BalTupleDefinitions + { + public static readonly IntermediateTupleDefinition WixStdbaOverridableVariable = new IntermediateTupleDefinition( + BalTupleDefinitionType.WixStdbaOverridableVariable.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixStdbaOverridableVariableTupleFields.Name), IntermediateFieldType.String), + }, + typeof(WixStdbaOverridableVariableTuple)); + } +} + +namespace WixToolset.Bal.Tuples +{ + using WixToolset.Data; + + public enum WixStdbaOverridableVariableTupleFields + { + Name, + } + + public class WixStdbaOverridableVariableTuple : IntermediateTuple + { + public WixStdbaOverridableVariableTuple() : base(BalTupleDefinitions.WixStdbaOverridableVariable, null, null) + { + } + + public WixStdbaOverridableVariableTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(BalTupleDefinitions.WixStdbaOverridableVariable, sourceLineNumber, id) + { + } + + public IntermediateField this[WixStdbaOverridableVariableTupleFields index] => this.Fields[(int)index]; + + public string Name + { + get => this.Fields[(int)WixStdbaOverridableVariableTupleFields.Name].AsString(); + set => this.Set((int)WixStdbaOverridableVariableTupleFields.Name, value); + } + } +} \ No newline at end of file diff --git a/src/wixext/WixBalExtension.csproj b/src/wixext/WixBalExtension.csproj deleted file mode 100644 index 3e9d382e..00000000 --- a/src/wixext/WixBalExtension.csproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - {BF720A63-9D7B-456E-B60C-8122852D9FED} - WixBalExtension - Library - WixToolset.Extensions - - - - - - - - $(RootNamespace).Data.Messages.resources - - - $(RootNamespace).Data.tables.xml - - - $(RootNamespace).Xsd.bal.xsd - PreserveNewest - - - WixToolset.Data.Serialize - WixToolset.Extensions.Serialize.Bal - - - Data\bal.wixlib - - - - - - - - - - - false - - - - diff --git a/src/wixext/WixToolset.Bal.wixext.csproj b/src/wixext/WixToolset.Bal.wixext.csproj new file mode 100644 index 00000000..49f891d3 --- /dev/null +++ b/src/wixext/WixToolset.Bal.wixext.csproj @@ -0,0 +1,30 @@ + + + + + + netstandard2.0 + WixToolset.Bal + WiX Toolset Bal Extension + WiX Toolset Bal Extension + true + build + + + + + + + + + + + + + + + + + + + diff --git a/src/wixext/WixToolset.Bal.wixext.targets b/src/wixext/WixToolset.Bal.wixext.targets new file mode 100644 index 00000000..70c5a19c --- /dev/null +++ b/src/wixext/WixToolset.Bal.wixext.targets @@ -0,0 +1,11 @@ + + + + + + $(MSBuildThisFileDirectory)..\tools\WixToolset.Bal.wixext.dll + + + + + diff --git a/src/wixext/messages.xml b/src/wixext/messages.xml deleted file mode 100644 index 9b11981d..00000000 --- a/src/wixext/messages.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - When the {0}/@{1} attribute is specified, the {0}/@PrereqPackage attribute must be set to "yes". - - - - - - - There must be at least one PrereqPackage when using the ManagedBootstrapperApplicationHost. - This is typically done by using the WixNetFxExtension and referencing one of the NetFxAsPrereq package groups. - - - - - There may only be one package in the bundle that has either the PrereqLicenseFile attribute or the PrereqLicenseUrl attribute. - - - - - WixStandardBootstrapperApplication doesn't support multiple BAFunctions DLLs. - - - - - The BAFunctions DLL Payload element must be located inside the BootstrapperApplication container. - - - - - - - WixStandardBootstrapperApplication doesn't automatically load BAFunctions.dll. Use the bal:BAFunctions attribute to indicate that it should be loaded. - - - - diff --git a/src/wixlib/BalExtension.wixproj b/src/wixlib/BalExtension.wixproj deleted file mode 100644 index e2898e83..00000000 --- a/src/wixlib/BalExtension.wixproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - {3444D952-F21C-496F-AB6B-56435BFD0787} - bal - Library - true - true - en-us - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/wixlib/bal.wixproj b/src/wixlib/bal.wixproj new file mode 100644 index 00000000..be15229b --- /dev/null +++ b/src/wixlib/bal.wixproj @@ -0,0 +1,62 @@ + + + + + + + {3444D952-F21C-496F-AB6B-56435BFD0787} + bal + Library + true + true + en-us + + + + + + + + + + + + + + + + + + mbahost + {12C87C77-3547-44F8-8134-29BC915CB19D} + + + wixstdba + {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA} + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + diff --git a/src/wixlib/packages.config b/src/wixlib/packages.config new file mode 100644 index 00000000..7964daed --- /dev/null +++ b/src/wixlib/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/wixstdba/packages.config b/src/wixstdba/packages.config new file mode 100644 index 00000000..41ba2f12 --- /dev/null +++ b/src/wixstdba/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/wixstdba/precomp.cpp b/src/wixstdba/precomp.cpp new file mode 100644 index 00000000..37664a1c --- /dev/null +++ b/src/wixstdba/precomp.cpp @@ -0,0 +1,3 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" diff --git a/src/wixstdba/precomp.h b/src/wixstdba/precomp.h index a0390fe2..925a80ce 100644 --- a/src/wixstdba/precomp.h +++ b/src/wixstdba/precomp.h @@ -3,7 +3,12 @@ #include + +#pragma warning(push) +#pragma warning(disable:4458) // declaration of 'xxx' hides class member #include +#pragma warning(pop) + #include #include #include diff --git a/src/wixstdba/wixstdba.vcxproj b/src/wixstdba/wixstdba.vcxproj index ddc0bc57..8ee9ace9 100644 --- a/src/wixstdba/wixstdba.vcxproj +++ b/src/wixstdba/wixstdba.vcxproj @@ -1,8 +1,11 @@ + + + + - Debug @@ -13,33 +16,27 @@ Win32 - - - Debug - ARM - - - Release - ARM - - {41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA} DynamicLibrary + v141 Unicode WixStdBA wixstdba.def - + + - $(WixRoot)src\libs\dutil\inc;$(WixRoot)src\burn\inc;$(WixRoot)src\libs\balutil\inc - comctl32.lib;gdiplus.lib;msimg32.lib;shlwapi.lib;wininet.lib;dutil.lib;balutil.lib;wixstdba.res + comctl32.lib;gdiplus.lib;msimg32.lib;shlwapi.lib;wininet.lib;wixstdba.res + + Create + @@ -93,7 +90,9 @@ - + + + Compiling message file... mc.exe -h "$(IntDir)." -r "$(IntDir)." -A -c -z wixstdba.messages "$(InputDir)wixstdba.mc" @@ -102,5 +101,15 @@ rc.exe -fo "$(OutDir)wixstdba.res" "$(IntDir)wixstdba.messages.rc" - + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + -- cgit v1.2.3-55-g6feb