Add WixInternalUIBootstrapperApplication as a new built-in BA.
Implements 6835
Sean Hall committed
Jul 19, 2022 at 15:17 UTC
913b6238417dceeb8440315e4669990756d17655
92 files changed
+3352
-151
src/api/burn/WixToolset.Mba.Core/IPackageInfo.cs
+5
@@ -67,6 +67,11 @@ namespace WixToolset.Mba.Core
67
/// </summary>
68
string PrereqLicenseUrl { get; }
69
70
+ /// <summary>
71
+ /// See <see cref="PrimaryPackageType"/>
72
+ /// </summary>
73
+ PrimaryPackageType PrimaryPackageType { get; }
74
+
75
/// <summary>
76
///
77
/// </summary>
src/api/burn/WixToolset.Mba.Core/PackageInfo.cs
+34
@@ -63,6 +63,37 @@ namespace WixToolset.Mba.Core
63
ChainBundle,
64
}
65
66
+ /// <summary>
67
+ /// Metadata for BAs like WixInternalUIBootstrapperApplication that only support one main package.
68
+ /// </summary>
69
+ public enum PrimaryPackageType
70
+ {
71
+ /// <summary>
72
+ /// Not a primary package.
73
+ /// </summary>
74
+ None,
75
+
76
+ /// <summary>
77
+ /// The default package if no architecture specific package is available for the current architecture.
78
+ /// </summary>
79
+ Default,
80
+
81
+ /// <summary>
82
+ /// The package to use on x86 machines.
83
+ /// </summary>
84
+ X86,
85
+
86
+ /// <summary>
87
+ /// The package to use on x64 machines.
88
+ /// </summary>
89
+ X64,
90
+
91
+ /// <summary>
92
+ /// The package to use on ARM64 machines.
93
+ /// </summary>
94
+ ARM64,
95
+ }
96
+
97
/// <summary>
98
/// Default implementation of <see cref="IPackageInfo"/>.
99
/// </summary>
@@ -116,6 +147,9 @@ namespace WixToolset.Mba.Core
147
/// <inheritdoc/>
148
public string PrereqLicenseUrl { get; internal set; }
149
150
+ /// <inheritdoc/>
151
+ public PrimaryPackageType PrimaryPackageType { get; internal set; }
152
+
153
/// <inheritdoc/>
154
public object CustomData { get; set; }
155
src/api/burn/balutil/balinfo.cpp
+27
@@ -529,6 +529,33 @@ static HRESULT ParseBalPackageInfoFromXml(
529
hr = XmlGetAttributeEx(pNode, L"DisplayInternalUICondition", &pPackage->sczDisplayInternalUICondition);
530
ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get DisplayInternalUICondition setting for package.");
531
532
+ hr = XmlGetAttributeEx(pNode, L"PrimaryPackageType", &scz);
533
+ ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get PrimaryPackageType setting for package.");
534
+
535
+ if (fXmlFound)
536
+ {
537
+ if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"default", -1))
538
+ {
539
+ pPackage->primaryPackageType = BAL_INFO_PRIMARY_PACKAGE_TYPE_DEFAULT;
540
+ }
541
+ else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"x86", -1))
542
+ {
543
+ pPackage->primaryPackageType = BAL_INFO_PRIMARY_PACKAGE_TYPE_X86;
544
+ }
545
+ else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"x64", -1))
546
+ {
547
+ pPackage->primaryPackageType = BAL_INFO_PRIMARY_PACKAGE_TYPE_X64;
548
+ }
549
+ else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"arm64", -1))
550
+ {
551
+ pPackage->primaryPackageType = BAL_INFO_PRIMARY_PACKAGE_TYPE_ARM64;
552
+ }
553
+ else
554
+ {
555
+ ExitWithRootFailure(hr, E_INVALIDARG, "Invalid value for WixBalPackageInfo/@PrimaryPackageType: %ls", scz);
556
+ }
557
+ }
558
+
559
ReleaseNullObject(pNode);
560
}
561
ExitOnFailure(hr, "Failed to parse all WixBalPackageInfo elements.");
src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
+11
-3
@@ -451,8 +451,8 @@ public: // IBootstrapperApplication
451
__in BOOTSTRAPPER_ERROR_TYPE errorType,
452
__in_z LPCWSTR wzPackageId,
453
__in DWORD dwCode,
454
- __in_z LPCWSTR /*wzError*/,
455
- __in DWORD /*dwUIHint*/,
454
+ __in_z LPCWSTR wzError,
455
+ __in DWORD dwUIHint,
456
__in DWORD /*cData*/,
457
__in_ecount_z_opt(cData) LPCWSTR* /*rgwzData*/,
458
__in int /*nRecommendation*/,
@@ -461,7 +461,15 @@ public: // IBootstrapperApplication
461
{
462
BalRetryErrorOccurred(wzPackageId, dwCode);
463
464
- if (CheckCanceled())
464
+ if (BOOTSTRAPPER_DISPLAY_EMBEDDED == m_display)
465
+ {
466
+ HRESULT hr = m_pEngine->SendEmbeddedError(dwCode, wzError, dwUIHint, pResult);
467
+ if (FAILED(hr))
468
+ {
469
+ *pResult = IDERROR;
470
+ }
471
+ }
472
+ else if (CheckCanceled())
473
{
474
*pResult = IDCANCEL;
475
}
src/api/burn/balutil/inc/balinfo.h
+10
@@ -20,6 +20,15 @@ typedef enum BAL_INFO_PACKAGE_TYPE
20
BAL_INFO_PACKAGE_TYPE_BUNDLE_CHAIN,
21
} BAL_INFO_PACKAGE_TYPE;
22
23
+typedef enum _BAL_INFO_PRIMARY_PACKAGE_TYPE
24
+{
25
+ BAL_INFO_PRIMARY_PACKAGE_TYPE_NONE,
26
+ BAL_INFO_PRIMARY_PACKAGE_TYPE_DEFAULT,
27
+ BAL_INFO_PRIMARY_PACKAGE_TYPE_X86,
28
+ BAL_INFO_PRIMARY_PACKAGE_TYPE_X64,
29
+ BAL_INFO_PRIMARY_PACKAGE_TYPE_ARM64,
30
+} BAL_INFO_PRIMARY_PACKAGE_TYPE;
31
+
32
typedef enum _BAL_INFO_RESTART
33
{
34
BAL_INFO_RESTART_UNKNOWN,
@@ -54,6 +63,7 @@ typedef struct _BAL_INFO_PACKAGE
63
BOOL fPrereqPackage;
64
LPWSTR sczPrereqLicenseFile;
65
LPWSTR sczPrereqLicenseUrl;
66
+ BAL_INFO_PRIMARY_PACKAGE_TYPE primaryPackageType;
67
LPVOID pvCustomData;
68
} BAL_INFO_PACKAGE;
69
src/api/wix/WixToolset.Data/Burn/BurnConstants.cs
+3
@@ -14,6 +14,9 @@ namespace WixToolset.Data.Burn
14
public const string BundleExtensionDataWixOutputStreamName = "wix-bextdata";
15
public const string BootstrapperApplicationDataWixOutputStreamName = "wix-badata.xml";
16
17
+ public const string BootstrapperApplicationDataNamespace = "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData";
18
+ public const string BundleExtensionDataNamespace = "http://wixtoolset.org/schemas/v4/BundleExtensionData";
19
+
20
public const string BootstrapperApplicationDataSymbolDefinitionTag = "WixBootstrapperApplicationData";
21
public const string BundleExtensionSearchSymbolDefinitionTag = "WixBundleExtensionSearch";
22
src/burn/engine/core.cpp
+3
-3
@@ -447,9 +447,6 @@ extern "C" HRESULT CorePlan(
447
BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL;
448
BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies.
449
450
- hr = PlanSetVariables(action, &pEngineState->variables);
451
- ExitOnFailure(hr, "Failed to update action.");
452
-
450
LogId(REPORT_STANDARD, MSG_PLAN_BEGIN, pEngineState->packages.cPackages, LoggingBurnActionToString(action));
451
452
fPlanBegan = TRUE;
@@ -469,6 +466,9 @@ extern "C" HRESULT CorePlan(
466
pEngineState->fPlanned = FALSE;
467
PlanReset(&pEngineState->plan, &pEngineState->variables, &pEngineState->containers, &pEngineState->packages, &pEngineState->layoutPayloads);
468
469
+ hr = PlanSetVariables(action, &pEngineState->variables);
470
+ ExitOnFailure(hr, "Failed to update action.");
471
+
472
// Remember the overall action state in the plan since it shapes the changes
473
// we make everywhere.
474
pEngineState->plan.action = action;
src/burn/engine/splashscreen.cpp
+1
-1
@@ -170,7 +170,7 @@ static DWORD WINAPI ThreadProc(
170
SPLASHSCREEN_INFO splashScreenInfo = { };
171
172
WNDCLASSW wc = { };
173
- BOOL fRegistered = TRUE;
173
+ BOOL fRegistered = FALSE;
174
175
BOOL fRet = FALSE;
176
MSG msg = { };
src/burn/engine/uithread.cpp
+1
-1
@@ -98,7 +98,7 @@ static DWORD WINAPI ThreadProc(
98
UITHREAD_INFO info = { };
99
100
WNDCLASSW wc = { };
101
- BOOL fRegistered = TRUE;
101
+ BOOL fRegistered = FALSE;
102
HWND hWnd = NULL;
103
104
BOOL fRet = FALSE;
src/ext/Bal/Bal.wixext.sln
+18
@@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bafunctions", "Samples\bafu
9
EndProject
10
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbahost", "mbahost\mbahost.vcxproj", "{12C87C77-3547-44F8-8134-29BC915CB19D}"
11
EndProject
12
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wixiuiba", "wixiuiba\wixiuiba.vcxproj", "{0F73E566-925C-448D-99CB-3A7F5DF399C8}"
13
+EndProject
14
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wixstdba", "wixstdba\wixstdba.vcxproj", "{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}"
15
EndProject
16
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "bal", "wixlib\bal.wixproj", "{3444D952-F21C-496F-AB6B-56435BFD0787}"
@@ -83,6 +85,22 @@ Global
85
{12C87C77-3547-44F8-8134-29BC915CB19D}.Release|x64.Build.0 = Release|x64
86
{12C87C77-3547-44F8-8134-29BC915CB19D}.Release|x86.ActiveCfg = Release|Win32
87
{12C87C77-3547-44F8-8134-29BC915CB19D}.Release|x86.Build.0 = Release|Win32
88
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Debug|Any CPU.ActiveCfg = Debug|Win32
89
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Debug|Any CPU.Build.0 = Debug|Win32
90
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Debug|ARM64.ActiveCfg = Debug|ARM64
91
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Debug|ARM64.Build.0 = Debug|ARM64
92
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Debug|x64.ActiveCfg = Debug|x64
93
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Debug|x64.Build.0 = Debug|x64
94
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Debug|x86.ActiveCfg = Debug|Win32
95
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Debug|x86.Build.0 = Debug|Win32
96
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Release|Any CPU.ActiveCfg = Release|Win32
97
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Release|Any CPU.Build.0 = Release|Win32
98
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Release|ARM64.ActiveCfg = Release|ARM64
99
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Release|ARM64.Build.0 = Release|ARM64
100
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Release|x64.ActiveCfg = Release|x64
101
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Release|x64.Build.0 = Release|x64
102
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Release|x86.ActiveCfg = Release|Win32
103
+ {0F73E566-925C-448D-99CB-3A7F5DF399C8}.Release|x86.Build.0 = Release|Win32
104
{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.ActiveCfg = Debug|Win32
105
{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|Any CPU.Build.0 = Debug|Win32
106
{41085A22-E6AA-4E8B-AB1B-DDEE0DC89DFA}.Debug|ARM64.ActiveCfg = Debug|ARM64
src/ext/Bal/bal.cmd
-8
@@ -14,14 +14,6 @@ nuget restore dnchost\packages.config || exit /b
14
msbuild -t:Restore -p:Configuration=%_C% || exit /b
15
16
:: Build
17
-msbuild -p:Configuration=%_C%;Platform=x86 dnchost\dnchost.vcxproj || exit /b
18
-msbuild -p:Configuration=%_C%;Platform=x64 dnchost\dnchost.vcxproj || exit /b
19
-msbuild -p:Configuration=%_C%;Platform=ARM64 dnchost\dnchost.vcxproj || exit /b
20
-
21
-msbuild -p:Configuration=%_C%;Platform=x86 mbahost\mbahost.vcxproj || exit /b
22
-msbuild -p:Configuration=%_C%;Platform=x64 mbahost\mbahost.vcxproj || exit /b
23
-msbuild -p:Configuration=%_C%;Platform=ARM64 mbahost\mbahost.vcxproj || exit /b
24
-
17
msbuild -p:Configuration=%_C%;Platform=x86 test\examples\TestEngine\Example.TestEngine.vcxproj || exit /b
18
msbuild -p:Configuration=%_C%;Platform=x64 test\examples\TestEngine\Example.TestEngine.vcxproj || exit /b
19
msbuild -p:Configuration=%_C%;Platform=ARM64 test\examples\TestEngine\Example.TestEngine.vcxproj || exit /b
src/ext/Bal/dnchost/dnchost.cpp
+5
-3
@@ -110,18 +110,18 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
110
{
111
if (DNCHOSTTYPE_SCD == vstate.type)
112
{
113
- vstate.prereqData.hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE;
113
+ vstate.prereqData.hrFatalError = E_DNCHOST_SCD_RUNTIME_FAILURE;
114
BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error.");
115
}
116
else if (vstate.prereqData.fCompleted)
117
{
118
hr = E_PREREQBA_INFINITE_LOOP;
119
BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
120
- vstate.prereqData.hrHostInitialization = hr;
120
+ vstate.prereqData.hrFatalError = hr;
121
}
122
else
123
{
124
- vstate.prereqData.hrHostInitialization = S_OK;
124
+ vstate.prereqData.hrFatalError = S_OK;
125
}
126
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr);
127
@@ -233,6 +233,8 @@ static HRESULT LoadDncConfiguration(
233
BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get AlwaysInstallPrereqs value.");
234
}
235
236
+ pState->prereqData.fPerformHelp = !pState->prereqData.fAlwaysInstallPrereqs;
237
+
238
pState->type = DNCHOSTTYPE_FDD;
239
240
hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixDncOptions", &pixnHost);
src/ext/Bal/mbahost/mbahost.cpp
+5
-3
@@ -144,17 +144,17 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
144
if (E_MBAHOST_NET452_ON_WIN7RTM == hr)
145
{
146
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.");
147
- vstate.prereqData.hrHostInitialization = hr;
147
+ vstate.prereqData.hrFatalError = hr;
148
}
149
else if (vstate.prereqData.fCompleted)
150
{
151
hr = E_PREREQBA_INFINITE_LOOP;
152
BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
153
- vstate.prereqData.hrHostInitialization = hr;
153
+ vstate.prereqData.hrFatalError = hr;
154
}
155
else
156
{
157
- vstate.prereqData.hrHostInitialization = S_OK;
157
+ vstate.prereqData.hrFatalError = S_OK;
158
}
159
160
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr);
@@ -306,6 +306,8 @@ static HRESULT LoadMbaConfiguration(
306
BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get AlwaysInstallPrereqs value.");
307
}
308
309
+ pState->prereqData.fPerformHelp = !pState->prereqData.fAlwaysInstallPrereqs;
310
+
311
LExit:
312
ReleaseObject(pixnHost);
313
ReleaseObject(pixdManifest);
src/ext/Bal/test/WixToolsetTest.Bal/BalExtensionFixture.cs
+6
@@ -143,6 +143,12 @@ namespace WixToolsetTest.Bal
143
{
144
"<WixMbaPrereqOptions AlwaysInstallPrereqs='1' />",
145
}, wixMbaPrereqOptionsElements);
146
+
147
+ var wixMbaPrereqInformationElements = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixMbaPrereqInformation");
148
+ WixAssert.CompareLineByLine(new[]
149
+ {
150
+ "<WixMbaPrereqInformation PackageId='wixnative.exe' />",
151
+ }, wixMbaPrereqInformationElements);
152
}
153
}
154
src/ext/Bal/test/WixToolsetTest.Bal/InternalUIBAFixture.cs
new
+474
@@ -0,0 +1,474 @@
1
+// 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.
2
+
3
+namespace WixToolsetTest.Bal
4
+{
5
+ using System;
6
+ using System.IO;
7
+ using System.Linq;
8
+ using WixBuildTools.TestSupport;
9
+ using WixToolset.Core.TestPackage;
10
+ using Xunit;
11
+
12
+ public class InternalUIBAFixture
13
+ {
14
+ [Fact]
15
+ public void CanBuildUsingWixIuiBa()
16
+ {
17
+ using (var fs = new DisposableFileSystem())
18
+ {
19
+ var baseFolder = fs.GetFolder();
20
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
21
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
22
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
23
+ var baFolderPath = Path.Combine(baseFolder, "ba");
24
+ var extractFolderPath = Path.Combine(baseFolder, "extract");
25
+
26
+ var compileResult = WixRunner.Execute(new[]
27
+ {
28
+ "build",
29
+ Path.Combine(bundleSourceFolder, "SinglePrimaryPackage.wxs"),
30
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
31
+ "-intermediateFolder", intermediateFolder,
32
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
33
+ "-o", bundleFile,
34
+ });
35
+ compileResult.AssertSuccess();
36
+
37
+ Assert.True(File.Exists(bundleFile));
38
+
39
+ var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
40
+ extractResult.AssertSuccess();
41
+
42
+ var balPackageInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixBalPackageInfo");
43
+ WixAssert.CompareLineByLine(new string[]
44
+ {
45
+ "<WixBalPackageInfo PackageId='test.msi' PrimaryPackageType='default' />",
46
+ }, balPackageInfos);
47
+
48
+ Assert.True(File.Exists(Path.Combine(baFolderPath, "mbapreq.thm")));
49
+ Assert.True(File.Exists(Path.Combine(baFolderPath, "mbapreq.wxl")));
50
+ }
51
+ }
52
+
53
+ [Fact]
54
+ public void CanBuildUsingWixIuiBaWithImplicitPrimaryPackage()
55
+ {
56
+ using (var fs = new DisposableFileSystem())
57
+ {
58
+ var baseFolder = fs.GetFolder();
59
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
60
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
61
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
62
+ var baFolderPath = Path.Combine(baseFolder, "ba");
63
+ var extractFolderPath = Path.Combine(baseFolder, "extract");
64
+
65
+ var compileResult = WixRunner.Execute(new[]
66
+ {
67
+ "build",
68
+ Path.Combine(bundleSourceFolder, "ImplicitPrimaryPackage.wxs"),
69
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
70
+ "-intermediateFolder", intermediateFolder,
71
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
72
+ "-o", bundleFile,
73
+ });
74
+ compileResult.AssertSuccess();
75
+
76
+ Assert.True(File.Exists(bundleFile));
77
+
78
+ var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
79
+ extractResult.AssertSuccess();
80
+
81
+ var balPackageInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixBalPackageInfo");
82
+ WixAssert.CompareLineByLine(new string[]
83
+ {
84
+ "<WixBalPackageInfo PackageId='test.msi' PrimaryPackageType='default' />",
85
+ }, balPackageInfos);
86
+
87
+ var mbaPrereqInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixMbaPrereqInformation");
88
+ WixAssert.CompareLineByLine(new[]
89
+ {
90
+ "<WixMbaPrereqInformation PackageId='wixnative.exe' />",
91
+ }, mbaPrereqInfos);
92
+
93
+ Assert.True(File.Exists(Path.Combine(baFolderPath, "mbapreq.thm")));
94
+ Assert.True(File.Exists(Path.Combine(baFolderPath, "mbapreq.wxl")));
95
+ }
96
+ }
97
+
98
+ [Fact]
99
+ public void CanBuildUsingWixIuiBaWithWarnings()
100
+ {
101
+ using (var fs = new DisposableFileSystem())
102
+ {
103
+ var baseFolder = fs.GetFolder();
104
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
105
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
106
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
107
+ var baFolderPath = Path.Combine(baseFolder, "ba");
108
+ var extractFolderPath = Path.Combine(baseFolder, "extract");
109
+
110
+ var compileResult = WixRunner.Execute(warningsAsErrors: false, new[]
111
+ {
112
+ "build",
113
+ Path.Combine(bundleSourceFolder, "IuiBaWarnings.wxs"),
114
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
115
+ "-intermediateFolder", intermediateFolder,
116
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
117
+ "-o", bundleFile,
118
+ });
119
+
120
+ WixAssert.CompareLineByLine(new[]
121
+ {
122
+ "WixInternalUIBootstrapperApplication does not support the value of 'force' for Cache on prereq packages. Prereq packages are only cached when they need to be installed.",
123
+ "WixInternalUIBootstrapperApplication ignores InstallCondition for the primary package so that the MSI UI is always shown.",
124
+ "WixInternalUIBootstrapperApplication ignores DisplayInternalUICondition for the primary package so that the MSI UI is always shown.",
125
+ "When using WixInternalUIBootstrapperApplication, all prereq packages should be before the primary package in the chain. The prereq packages are always installed before the primary package.",
126
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
127
+
128
+ compileResult.AssertSuccess();
129
+
130
+ Assert.True(File.Exists(bundleFile));
131
+
132
+ var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
133
+ extractResult.AssertSuccess();
134
+
135
+ var balPackageInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixBalPackageInfo");
136
+ WixAssert.CompareLineByLine(new string[]
137
+ {
138
+ "<WixBalPackageInfo PackageId='test.msi' DisplayInternalUICondition='DISPLAYTEST' PrimaryPackageType='default' />",
139
+ }, balPackageInfos);
140
+
141
+ var mbaPrereqInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixMbaPrereqInformation");
142
+ WixAssert.CompareLineByLine(new[]
143
+ {
144
+ "<WixMbaPrereqInformation PackageId='wixnative.exe' />",
145
+ }, mbaPrereqInfos);
146
+
147
+ Assert.True(File.Exists(Path.Combine(baFolderPath, "mbapreq.thm")));
148
+ Assert.True(File.Exists(Path.Combine(baFolderPath, "mbapreq.wxl")));
149
+ }
150
+ }
151
+
152
+ [Fact]
153
+ public void CannotBuildUsingWixIuiBaWithAllPrereqPackages()
154
+ {
155
+ using (var fs = new DisposableFileSystem())
156
+ {
157
+ var baseFolder = fs.GetFolder();
158
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
159
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
160
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
161
+
162
+ var compileResult = WixRunner.Execute(new[]
163
+ {
164
+ "build",
165
+ Path.Combine(bundleSourceFolder, "AllPrereqPackages.wxs"),
166
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
167
+ "-intermediateFolder", intermediateFolder,
168
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
169
+ "-o", bundleFile,
170
+ });
171
+
172
+ WixAssert.CompareLineByLine(new[]
173
+ {
174
+ "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".",
175
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
176
+
177
+ Assert.Equal(6808, compileResult.ExitCode);
178
+ }
179
+ }
180
+
181
+ [Fact]
182
+ public void CannotBuildUsingWixIuiBaWithImplicitNonMsiPrimaryPackage()
183
+ {
184
+ using (var fs = new DisposableFileSystem())
185
+ {
186
+ var baseFolder = fs.GetFolder();
187
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
188
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
189
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
190
+
191
+ var compileResult = WixRunner.Execute(new[]
192
+ {
193
+ "build",
194
+ Path.Combine(bundleSourceFolder, "ImplicitNonMsiPrimaryPackage.wxs"),
195
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
196
+ "-intermediateFolder", intermediateFolder,
197
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
198
+ "-o", bundleFile,
199
+ });
200
+
201
+ WixAssert.CompareLineByLine(new[]
202
+ {
203
+ "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.",
204
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
205
+
206
+ Assert.Equal(6811, compileResult.ExitCode);
207
+ }
208
+ }
209
+
210
+ [Fact]
211
+ public void CannotBuildUsingWixIuiBaWithImplicitPrimaryPackageEnableFeatureSelection()
212
+ {
213
+ using (var fs = new DisposableFileSystem())
214
+ {
215
+ var baseFolder = fs.GetFolder();
216
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
217
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
218
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
219
+
220
+ var compileResult = WixRunner.Execute(new[]
221
+ {
222
+ "build",
223
+ Path.Combine(bundleSourceFolder, "ImplicitPrimaryPackageEnableFeatureSelection.wxs"),
224
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
225
+ "-intermediateFolder", intermediateFolder,
226
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
227
+ "-o", bundleFile,
228
+ });
229
+
230
+ WixAssert.CompareLineByLine(new[]
231
+ {
232
+ "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.",
233
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
234
+
235
+ Assert.Equal(6811, compileResult.ExitCode);
236
+ }
237
+ }
238
+
239
+ [Fact]
240
+ public void CannotBuildUsingWixIuiBaWithMultipleNonPermanentNonPrimaryPackages()
241
+ {
242
+ using (var fs = new DisposableFileSystem())
243
+ {
244
+ var baseFolder = fs.GetFolder();
245
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
246
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
247
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
248
+
249
+ var compileResult = WixRunner.Execute(new[]
250
+ {
251
+ "build",
252
+ Path.Combine(bundleSourceFolder, "MultipleNonPermanentNonPrimaryPackages.wxs"),
253
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
254
+ "-intermediateFolder", intermediateFolder,
255
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
256
+ "-o", bundleFile,
257
+ });
258
+
259
+ WixAssert.CompareLineByLine(new[]
260
+ {
261
+ "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.",
262
+ "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.",
263
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
264
+
265
+ Assert.Equal(6811, compileResult.ExitCode);
266
+ }
267
+ }
268
+
269
+ [Fact]
270
+ public void CannotBuildUsingWixIuiBaWithMultiplePrimaryPackagesOfSameType()
271
+ {
272
+ using (var fs = new DisposableFileSystem())
273
+ {
274
+ var baseFolder = fs.GetFolder();
275
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
276
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
277
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
278
+
279
+ var compileResult = WixRunner.Execute(new[]
280
+ {
281
+ "build",
282
+ Path.Combine(bundleSourceFolder, "MultipleDefaultPrimaryPackages.wxs"),
283
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
284
+ "-intermediateFolder", intermediateFolder,
285
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
286
+ "-o", bundleFile,
287
+ });
288
+
289
+ WixAssert.CompareLineByLine(new[]
290
+ {
291
+ "There may only be one package in the bundle with PrimaryPackageType of 'default'.",
292
+ "The location of the package related to the previous error.",
293
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
294
+
295
+ Assert.Equal(6810, compileResult.ExitCode);
296
+ }
297
+ }
298
+
299
+ [Fact]
300
+ public void CannotBuildUsingWixIuiBaWithNoDefaultPrimaryPackage()
301
+ {
302
+ using (var fs = new DisposableFileSystem())
303
+ {
304
+ var baseFolder = fs.GetFolder();
305
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
306
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
307
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
308
+
309
+ var compileResult = WixRunner.Execute(new[]
310
+ {
311
+ "build",
312
+ Path.Combine(bundleSourceFolder, "NoDefaultPrimaryPackage.wxs"),
313
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
314
+ "-intermediateFolder", intermediateFolder,
315
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
316
+ "-o", bundleFile,
317
+ });
318
+
319
+ WixAssert.CompareLineByLine(new[]
320
+ {
321
+ "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".",
322
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
323
+
324
+ Assert.Equal(6808, compileResult.ExitCode);
325
+ }
326
+ }
327
+
328
+ [Fact]
329
+ public void CannotBuildUsingWixIuiBaWithNonMsiPrimaryPackage()
330
+ {
331
+ using (var fs = new DisposableFileSystem())
332
+ {
333
+ var baseFolder = fs.GetFolder();
334
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
335
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
336
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
337
+
338
+ var compileResult = WixRunner.Execute(new[]
339
+ {
340
+ "build",
341
+ Path.Combine(bundleSourceFolder, "NonMsiPrimaryPackage.wxs"),
342
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
343
+ "-intermediateFolder", intermediateFolder,
344
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
345
+ "-o", bundleFile,
346
+ });
347
+
348
+ WixAssert.CompareLineByLine(new[]
349
+ {
350
+ "When using WixInternalUIBootstrapperApplication, each primary package must be an MsiPackage.",
351
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
352
+
353
+ Assert.Equal(6814, compileResult.ExitCode);
354
+ }
355
+ }
356
+
357
+ [Fact]
358
+ public void CannotBuildUsingWixIuiBaWithNonPermanentPrereqPackage()
359
+ {
360
+ using (var fs = new DisposableFileSystem())
361
+ {
362
+ var baseFolder = fs.GetFolder();
363
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
364
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
365
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
366
+
367
+ var compileResult = WixRunner.Execute(new[]
368
+ {
369
+ "build",
370
+ Path.Combine(bundleSourceFolder, "NonPermanentPrereqPackage.wxs"),
371
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
372
+ "-intermediateFolder", intermediateFolder,
373
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
374
+ "-o", bundleFile,
375
+ });
376
+
377
+ WixAssert.CompareLineByLine(new[]
378
+ {
379
+ "When using WixInternalUIBootstrapperApplication and bal:PrereqPackage is set to 'yes', the package must be permanent.",
380
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
381
+
382
+ Assert.Equal(6812, compileResult.ExitCode);
383
+ }
384
+ }
385
+
386
+ [Fact]
387
+ public void CannotBuildUsingWixIuiBaWithPermanentPrimaryPackage()
388
+ {
389
+ using (var fs = new DisposableFileSystem())
390
+ {
391
+ var baseFolder = fs.GetFolder();
392
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
393
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
394
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
395
+
396
+ var compileResult = WixRunner.Execute(new[]
397
+ {
398
+ "build",
399
+ Path.Combine(bundleSourceFolder, "PermanentPrimaryPackage.wxs"),
400
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
401
+ "-intermediateFolder", intermediateFolder,
402
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
403
+ "-o", bundleFile,
404
+ });
405
+
406
+ WixAssert.CompareLineByLine(new[]
407
+ {
408
+ "When using WixInternalUIBootstrapperApplication, packages with the bal:PrimaryPackageType attribute must not be permanent.",
409
+ "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".",
410
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
411
+
412
+ Assert.Equal(6808, compileResult.ExitCode);
413
+ }
414
+ }
415
+
416
+ [Fact]
417
+ public void CannotBuildUsingWixIuiBaWithPrimaryPackageEnableFeatureSelection()
418
+ {
419
+ using (var fs = new DisposableFileSystem())
420
+ {
421
+ var baseFolder = fs.GetFolder();
422
+ var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
423
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
424
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
425
+
426
+ var compileResult = WixRunner.Execute(new[]
427
+ {
428
+ "build",
429
+ Path.Combine(bundleSourceFolder, "PrimaryPackageEnableFeatureSelection.wxs"),
430
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
431
+ "-intermediateFolder", intermediateFolder,
432
+ "-bindpath", TestData.Get(@"TestData\WixStdBa\Data"),
433
+ "-o", bundleFile,
434
+ });
435
+
436
+ WixAssert.CompareLineByLine(new[]
437
+ {
438
+ "When using WixInternalUIBootstrapperApplication, primary packages must not have feature selection enabled because it interferes with the user selecting feature through the MSI UI.",
439
+ "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".",
440
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
441
+
442
+ Assert.Equal(6808, compileResult.ExitCode);
443
+ }
444
+ }
445
+
446
+ [Fact]
447
+ public void CannotBuildUsingWixIuiBaWithPrimaryPrereqPackage()
448
+ {
449
+ using (var fs = new DisposableFileSystem())
450
+ {
451
+ var baseFolder = fs.GetFolder();
452
+ var wixlibFile = Path.Combine(baseFolder, "bin", "test.wixlib");
453
+ var bundleSourceFolder = TestData.Get(@"TestData\WixIuiBa");
454
+ var intermediateFolder = Path.Combine(baseFolder, "obj");
455
+
456
+ var compileResult = WixRunner.Execute(new[]
457
+ {
458
+ "build",
459
+ Path.Combine(bundleSourceFolder, "PrimaryPrereqPackage.wxs"),
460
+ "-ext", TestData.Get(@"WixToolset.Bal.wixext.dll"),
461
+ "-intermediateFolder", intermediateFolder,
462
+ "-o", wixlibFile,
463
+ });
464
+
465
+ WixAssert.CompareLineByLine(new[]
466
+ {
467
+ "The MsiPackage/@PrereqPackage attribute's value, 'yes', cannot be specified with attribute PrimaryPackageType present.",
468
+ }, compileResult.Messages.Select(m => m.ToString()).ToArray());
469
+
470
+ Assert.Equal(193, compileResult.ExitCode);
471
+ }
472
+ }
473
+ }
474
+}
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/AllPrereqPackages.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{1CD73801-0B08-4B39-B371-00DA49EF715F}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage bal:PrereqPackage="yes" Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" />
10
+ <MsiPackage bal:PrereqPackage="yes" Permanent="yes" SourceFile="test.msi" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/ImplicitNonMsiPrimaryPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{1CD73801-0B08-4B39-B371-00DA49EF715F}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <MsiPackage SourceFile="test.msi" Permanent="yes" />
10
+ <ExePackage UninstallArguments="" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/ImplicitPrimaryPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{1CD73801-0B08-4B39-B371-00DA49EF715F}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" />
10
+ <MsiPackage SourceFile="test.msi" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/ImplicitPrimaryPackageEnableFeatureSelection.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{1CD73801-0B08-4B39-B371-00DA49EF715F}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" />
10
+ <MsiPackage SourceFile="test.msi" EnableFeatureSelection="yes" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/IuibaWarnings.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{1CD73801-0B08-4B39-B371-00DA49EF715F}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <MsiPackage SourceFile="test.msi" InstallCondition="INSTALLTEST" bal:DisplayInternalUICondition="DISPLAYTEST" />
10
+ <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" Cache="force" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/MultipleDefaultPrimaryPackages.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{5C7B7C41-B3A9-4FFF-952A-B6D68320B9B4}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <MsiPackage Id="One" SourceFile="test.msi" bal:PrimaryPackageType="default" />
10
+ <MsiPackage Id="Two" CacheId="dontdothis" SourceFile="test.msi" bal:PrimaryPackageType="default" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/MultipleNonPermanentNonPrimaryPackages.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{1CD73801-0B08-4B39-B371-00DA49EF715F}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage UninstallArguments="" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" />
10
+ <MsiPackage SourceFile="test.msi" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/NoDefaultPrimaryPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{1CD73801-0B08-4B39-B371-00DA49EF715F}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" />
10
+ <MsiPackage bal:PrimaryPackageType="x86" SourceFile="test.msi" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/NonMsiPrimaryPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{1CD73801-0B08-4B39-B371-00DA49EF715F}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage UninstallArguments="" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" bal:PrimaryPackageType="x86" />
10
+ <MsiPackage SourceFile="test.msi" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/NonPermanentPrereqPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{5C7B7C41-B3A9-4FFF-952A-B6D68320B9B4}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage UninstallArguments="" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" bal:PrereqPackage="yes" />
10
+ <MsiPackage SourceFile="test.msi" bal:PrimaryPackageType="default" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/PermanentPrimaryPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{5C7B7C41-B3A9-4FFF-952A-B6D68320B9B4}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" bal:PrereqPackage="yes" />
10
+ <MsiPackage SourceFile="test.msi" bal:PrimaryPackageType="default" Permanent="yes" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/PrimaryPackageEnableFeatureSelection.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{5C7B7C41-B3A9-4FFF-952A-B6D68320B9B4}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" bal:PrereqPackage="yes" />
10
+ <MsiPackage SourceFile="test.msi" bal:PrimaryPackageType="default" EnableFeatureSelection="yes" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/PrimaryPrereqPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{5C7B7C41-B3A9-4FFF-952A-B6D68320B9B4}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" bal:PrereqPackage="yes" />
10
+ <MsiPackage SourceFile="test.msi" bal:PrimaryPackageType="default" bal:PrereqPackage="yes" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/test/WixToolsetTest.Bal/TestData/WixIuiBa/SinglePrimaryPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3
+ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4
+ <Bundle Name="WixIuiBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="{5C7B7C41-B3A9-4FFF-952A-B6D68320B9B4}">
5
+ <BootstrapperApplication>
6
+ <bal:WixInternalUIBootstrapperApplication />
7
+ </BootstrapperApplication>
8
+ <Chain>
9
+ <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" bal:PrereqPackage="yes" />
10
+ <MsiPackage SourceFile="test.msi" bal:PrimaryPackageType="default" />
11
+ </Chain>
12
+ </Bundle>
13
+</Wix>
src/ext/Bal/wixext/BalBurnBackendExtension.cs
+284
-10
@@ -5,6 +5,8 @@ namespace WixToolset.Bal
5
using System;
6
using System.Collections.Generic;
7
using System.Linq;
8
+ using System.Text;
9
+ using System.Xml;
10
using WixToolset.Bal.Symbols;
11
using WixToolset.Data;
12
using WixToolset.Data.Burn;
@@ -29,12 +31,48 @@ namespace WixToolset.Bal
31
32
protected override IReadOnlyCollection<IntermediateSymbolDefinition> SymbolDefinitions => BurnSymbolDefinitions;
33
34
+ public override bool TryProcessSymbol(IntermediateSection section, IntermediateSymbol symbol)
35
+ {
36
+ if (symbol is WixBalPackageInfoSymbol balPackageInfoSymbol)
37
+ {
38
+ // There might be a more efficient way to do this,
39
+ // but this is an easy way to ensure we're creating valid XML.
40
+ var sb = new StringBuilder();
41
+ using (var writer = XmlWriter.Create(sb))
42
+ {
43
+ writer.WriteStartElement(symbol.Definition.Name, BurnConstants.BootstrapperApplicationDataNamespace);
44
+
45
+ writer.WriteAttributeString("PackageId", balPackageInfoSymbol.PackageId);
46
+
47
+ if (balPackageInfoSymbol.DisplayInternalUICondition != null)
48
+ {
49
+ writer.WriteAttributeString("DisplayInternalUICondition", balPackageInfoSymbol.DisplayInternalUICondition);
50
+ }
51
+
52
+ if (balPackageInfoSymbol.PrimaryPackageType != BalPrimaryPackageType.None)
53
+ {
54
+ writer.WriteAttributeString("PrimaryPackageType", balPackageInfoSymbol.PrimaryPackageType.ToString().ToLower());
55
+ }
56
+
57
+ writer.WriteEndElement();
58
+ }
59
+
60
+ this.BackendHelper.AddBootstrapperApplicationData(sb.ToString());
61
+
62
+ return true;
63
+ }
64
+ else
65
+ {
66
+ return base.TryProcessSymbol(section, symbol);
67
+ }
68
+ }
69
+
70
public override void SymbolsFinalized(IntermediateSection section)
71
{
72
base.SymbolsFinalized(section);
73
74
this.VerifyBalConditions(section);
37
- this.VerifyBalPackageInfos(section);
75
+ this.VerifyDisplayInternalUICondition(section);
76
this.VerifyOverridableVariables(section);
77
78
var baSymbol = section.Symbols.OfType<WixBootstrapperApplicationDllSymbol>().SingleOrDefault();
@@ -44,24 +82,31 @@ namespace WixToolset.Bal
82
return;
83
}
84
85
+ var isIuiBA = baId.StartsWith("WixInternalUIBootstrapperApplication");
86
var isStdBA = baId.StartsWith("WixStandardBootstrapperApplication");
87
var isMBA = baId.StartsWith("WixManagedBootstrapperApplicationHost");
88
var isDNC = baId.StartsWith("WixDotNetCoreBootstrapperApplicationHost");
89
var isSCD = isDNC && this.VerifySCD(section);
90
91
+ if (isIuiBA)
92
+ {
93
+ // This needs to happen before VerifyPrereqPackages because it can add prereq packages.
94
+ this.VerifyPrimaryPackages(section);
95
+ }
96
+
97
if (isDNC)
98
{
99
this.FinalizeBAFactorySymbol(section);
100
}
101
57
- if (isStdBA || isMBA || isDNC)
102
+ if (isIuiBA || isStdBA || isMBA || isDNC)
103
{
104
this.VerifyBAFunctions(section);
105
}
106
62
- if (isMBA || (isDNC && !isSCD))
107
+ if (isIuiBA || isMBA || (isDNC && !isSCD))
108
{
64
- this.VerifyPrereqPackages(section, isDNC);
109
+ this.VerifyPrereqPackages(section, isDNC, isIuiBA);
110
}
111
}
112
@@ -133,12 +178,241 @@ namespace WixToolset.Bal
178
}
179
}
180
136
- private void VerifyBalPackageInfos(IntermediateSection section)
181
+ private void VerifyDisplayInternalUICondition(IntermediateSection section)
182
+ {
183
+ foreach (var balPackageInfoSymbol in section.Symbols.OfType<WixBalPackageInfoSymbol>().ToList())
184
+ {
185
+ if (balPackageInfoSymbol.DisplayInternalUICondition != null)
186
+ {
187
+ this.BackendHelper.ValidateBundleCondition(balPackageInfoSymbol.SourceLineNumbers, "*Package", "bal:DisplayInternalUICondition", balPackageInfoSymbol.DisplayInternalUICondition, BundleConditionPhase.Plan);
188
+ }
189
+ }
190
+ }
191
+
192
+ private void VerifyPrimaryPackages(IntermediateSection section)
193
+ {
194
+ WixBalPackageInfoSymbol defaultPrimaryPackage = null;
195
+ WixBalPackageInfoSymbol x86PrimaryPackage = null;
196
+ WixBalPackageInfoSymbol x64PrimaryPackage = null;
197
+ WixBalPackageInfoSymbol arm64PrimaryPackage = null;
198
+ var nonPermanentNonPrimaryPackages = new List<WixBundlePackageSymbol>();
199
+
200
+ var balPackageInfoSymbolsByPackageId = section.Symbols.OfType<WixBalPackageInfoSymbol>().ToDictionary(x => x.PackageId);
201
+ var mbaPrereqInfoSymbolsByPackageId = section.Symbols.OfType<WixMbaPrereqInformationSymbol>().ToDictionary(x => x.PackageId);
202
+ var msiPackageSymbolsByPackageId = section.Symbols.OfType<WixBundleMsiPackageSymbol>().ToDictionary(x => x.Id.Id);
203
+ var packageSymbols = section.Symbols.OfType<WixBundlePackageSymbol>().ToList();
204
+ foreach (var packageSymbol in packageSymbols)
205
+ {
206
+ var packageId = packageSymbol.Id?.Id;
207
+ var isPrereq = false;
208
+ var primaryPackageType = BalPrimaryPackageType.None;
209
+
210
+ if (mbaPrereqInfoSymbolsByPackageId.TryGetValue(packageId, out var _))
211
+ {
212
+ isPrereq = true;
213
+ }
214
+
215
+ if (balPackageInfoSymbolsByPackageId.TryGetValue(packageId, out var balPackageInfoSymbol))
216
+ {
217
+ primaryPackageType = balPackageInfoSymbol.PrimaryPackageType;
218
+ }
219
+
220
+ if (packageSymbol.Permanent)
221
+ {
222
+ if (primaryPackageType != BalPrimaryPackageType.None)
223
+ {
224
+ this.Messaging.Write(BalErrors.IuibaPermanentPrimaryPackageType(packageSymbol.SourceLineNumbers));
225
+ }
226
+ else
227
+ {
228
+ if (!isPrereq)
229
+ {
230
+ var prereqInfoSymbol = section.AddSymbol(new WixMbaPrereqInformationSymbol(packageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Global, packageId))
231
+ {
232
+ PackageId = packageId,
233
+ });
234
+
235
+ mbaPrereqInfoSymbolsByPackageId.Add(packageId, prereqInfoSymbol);
236
+ }
237
+
238
+ this.VerifyIuibaPrereqPackage(packageSymbol);
239
+ }
240
+ }
241
+ else
242
+ {
243
+ if (isPrereq)
244
+ {
245
+ if (primaryPackageType == BalPrimaryPackageType.None)
246
+ {
247
+ this.Messaging.Write(BalErrors.IuibaNonPermanentPrereqPackage(packageSymbol.SourceLineNumbers));
248
+ }
249
+ else
250
+ {
251
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute(
252
+ packageSymbol.SourceLineNumbers,
253
+ packageSymbol.Type + "Package",
254
+ "PrereqPackage",
255
+ "yes",
256
+ "PrimaryPackageType"));
257
+ }
258
+ }
259
+ else if (primaryPackageType == BalPrimaryPackageType.None)
260
+ {
261
+ nonPermanentNonPrimaryPackages.Add(packageSymbol);
262
+ }
263
+ else if (packageSymbol.Type != WixBundlePackageType.Msi)
264
+ {
265
+ this.Messaging.Write(BalErrors.IuibaNonMsiPrimaryPackage(packageSymbol.SourceLineNumbers));
266
+ }
267
+ else if (!msiPackageSymbolsByPackageId.TryGetValue(packageId, out var msiPackageSymbol))
268
+ {
269
+ throw new WixException($"Missing WixBundleMsiPackageSymbol for package '{packageId}'");
270
+ }
271
+ else if (msiPackageSymbol.EnableFeatureSelection)
272
+ {
273
+ this.Messaging.Write(BalErrors.IuibaPrimaryPackageEnableFeatureSelection(packageSymbol.SourceLineNumbers));
274
+ }
275
+ else
276
+ {
277
+ if (primaryPackageType == BalPrimaryPackageType.Default)
278
+ {
279
+ if (defaultPrimaryPackage == null)
280
+ {
281
+ defaultPrimaryPackage = balPackageInfoSymbol;
282
+ }
283
+ else
284
+ {
285
+ this.Messaging.Write(BalErrors.MultiplePrimaryPackageType(balPackageInfoSymbol.SourceLineNumbers, "default"));
286
+ this.Messaging.Write(BalErrors.MultiplePrimaryPackageType2(defaultPrimaryPackage.SourceLineNumbers));
287
+ }
288
+ }
289
+ else if (balPackageInfoSymbol.PrimaryPackageType == BalPrimaryPackageType.X86)
290
+ {
291
+ if (x86PrimaryPackage == null)
292
+ {
293
+ x86PrimaryPackage = balPackageInfoSymbol;
294
+ }
295
+ else
296
+ {
297
+ this.Messaging.Write(BalErrors.MultiplePrimaryPackageType(balPackageInfoSymbol.SourceLineNumbers, "x86"));
298
+ this.Messaging.Write(BalErrors.MultiplePrimaryPackageType2(x86PrimaryPackage.SourceLineNumbers));
299
+ }
300
+ }
301
+ else if (balPackageInfoSymbol.PrimaryPackageType == BalPrimaryPackageType.X64)
302
+ {
303
+ if (x64PrimaryPackage == null)
304
+ {
305
+ x64PrimaryPackage = balPackageInfoSymbol;
306
+ }
307
+ else
308
+ {
309
+ this.Messaging.Write(BalErrors.MultiplePrimaryPackageType(balPackageInfoSymbol.SourceLineNumbers, "x64"));
310
+ this.Messaging.Write(BalErrors.MultiplePrimaryPackageType2(x64PrimaryPackage.SourceLineNumbers));
311
+ }
312
+ }
313
+ else if (balPackageInfoSymbol.PrimaryPackageType == BalPrimaryPackageType.ARM64)
314
+ {
315
+ if (arm64PrimaryPackage == null)
316
+ {
317
+ arm64PrimaryPackage = balPackageInfoSymbol;
318
+ }
319
+ else
320
+ {
321
+ this.Messaging.Write(BalErrors.MultiplePrimaryPackageType(balPackageInfoSymbol.SourceLineNumbers, "arm64"));
322
+ this.Messaging.Write(BalErrors.MultiplePrimaryPackageType2(arm64PrimaryPackage.SourceLineNumbers));
323
+ }
324
+ }
325
+ else
326
+ {
327
+ throw new NotImplementedException();
328
+ }
329
+
330
+ this.VerifyIuibaPrimaryPackage(packageSymbol, balPackageInfoSymbol);
331
+ }
332
+ }
333
+ }
334
+
335
+ if (defaultPrimaryPackage == null && nonPermanentNonPrimaryPackages.Count == 1)
336
+ {
337
+ var packageSymbol = nonPermanentNonPrimaryPackages[0];
338
+
339
+ if (packageSymbol.Type == WixBundlePackageType.Msi)
340
+ {
341
+ var packageId = packageSymbol.Id?.Id;
342
+ var msiPackageSymbol = section.Symbols.OfType<WixBundleMsiPackageSymbol>()
343
+ .SingleOrDefault(x => x.Id.Id == packageId);
344
+ if (!msiPackageSymbol.EnableFeatureSelection)
345
+ {
346
+ if (!balPackageInfoSymbolsByPackageId.TryGetValue(packageId, out var balPackageInfoSymbol))
347
+ {
348
+ balPackageInfoSymbol = section.AddSymbol(new WixBalPackageInfoSymbol(packageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Global, packageId))
349
+ {
350
+ PackageId = packageId,
351
+ });
352
+
353
+ balPackageInfoSymbolsByPackageId.Add(packageId, balPackageInfoSymbol);
354
+ }
355
+
356
+ balPackageInfoSymbol.PrimaryPackageType = BalPrimaryPackageType.Default;
357
+ defaultPrimaryPackage = balPackageInfoSymbol;
358
+ nonPermanentNonPrimaryPackages.RemoveAt(0);
359
+
360
+ this.VerifyIuibaPrimaryPackage(packageSymbol, balPackageInfoSymbol);
361
+ }
362
+ }
363
+ }
364
+
365
+ if (nonPermanentNonPrimaryPackages.Count > 0)
366
+ {
367
+ foreach (var packageSymbol in nonPermanentNonPrimaryPackages)
368
+ {
369
+ this.Messaging.Write(BalErrors.IuibaNonPermanentNonPrimaryPackage(packageSymbol.SourceLineNumbers));
370
+ }
371
+ }
372
+ else if (defaultPrimaryPackage == null)
373
+ {
374
+ this.Messaging.Write(BalErrors.MissingIUIPrimaryPackage());
375
+ }
376
+ else
377
+ {
378
+ var foundPrimaryPackage = false;
379
+ var chainPackageGroupSymbols = section.Symbols.OfType<WixGroupSymbol>()
380
+ .Where(x => x.ChildType == ComplexReferenceChildType.Package &&
381
+ x.ParentType == ComplexReferenceParentType.PackageGroup &&
382
+ x.ParentId == BurnConstants.BundleChainPackageGroupId);
383
+ foreach (var chainPackageGroupSymbol in chainPackageGroupSymbols)
384
+ {
385
+ var packageId = chainPackageGroupSymbol.ChildId;
386
+ if (balPackageInfoSymbolsByPackageId.TryGetValue(packageId, out var balPackageInfo) && balPackageInfo.PrimaryPackageType != BalPrimaryPackageType.None)
387
+ {
388
+ foundPrimaryPackage = true;
389
+ }
390
+ else if (foundPrimaryPackage && mbaPrereqInfoSymbolsByPackageId.TryGetValue(packageId, out var mbaPrereqInformationSymbol))
391
+ {
392
+ this.Messaging.Write(BalWarnings.IuibaPrereqPackageAfterPrimaryPackage(chainPackageGroupSymbol.SourceLineNumbers));
393
+ }
394
+ }
395
+ }
396
+ }
397
+
398
+ private void VerifyIuibaPrereqPackage(WixBundlePackageSymbol packageSymbol)
399
+ {
400
+ if (packageSymbol.Cache == BundleCacheType.Force)
401
+ {
402
+ this.Messaging.Write(BalWarnings.IuibaForceCachePrereq(packageSymbol.SourceLineNumbers));
403
+ }
404
+ }
405
+
406
+ private void VerifyIuibaPrimaryPackage(WixBundlePackageSymbol packageSymbol, WixBalPackageInfoSymbol balPackageInfoSymbol)
407
{
138
- var balPackageInfoSymbols = section.Symbols.OfType<WixBalPackageInfoSymbol>().ToList();
139
- foreach (var balPackageInfoSymbol in balPackageInfoSymbols)
408
+ if (packageSymbol.InstallCondition != null)
409
+ {
410
+ this.Messaging.Write(BalWarnings.IuibaPrimaryPackageInstallCondition(packageSymbol.SourceLineNumbers));
411
+ }
412
+
413
+ if (balPackageInfoSymbol.DisplayInternalUICondition != null)
414
{
141
- this.BackendHelper.ValidateBundleCondition(balPackageInfoSymbol.SourceLineNumbers, "*Package", "bal:DisplayInternalUICondition", balPackageInfoSymbol.DisplayInternalUICondition, BundleConditionPhase.Plan);
415
+ this.Messaging.Write(BalWarnings.IuibaPrimaryPackageDisplayInternalUICondition(packageSymbol.SourceLineNumbers));
416
}
417
}
418
@@ -161,10 +435,10 @@ namespace WixToolset.Bal
435
}
436
}
437
164
- private void VerifyPrereqPackages(IntermediateSection section, bool isDNC)
438
+ private void VerifyPrereqPackages(IntermediateSection section, bool isDNC, bool isIuiBA)
439
{
440
var prereqInfoSymbols = section.Symbols.OfType<WixMbaPrereqInformationSymbol>().ToList();
167
- if (prereqInfoSymbols.Count == 0)
441
+ if (!isIuiBA && prereqInfoSymbols.Count == 0)
442
{
443
var message = isDNC ? BalErrors.MissingDNCPrereq() : BalErrors.MissingMBAPrereq();
444
this.Messaging.Write(message);
src/ext/Bal/wixext/BalCompiler.cs
+200
-69
@@ -16,7 +16,8 @@ namespace WixToolset.Bal
16
/// </summary>
17
public sealed class BalCompiler : BaseCompilerExtension
18
{
19
- private readonly Dictionary<string, WixMbaPrereqInformationSymbol> prereqInfoSymbolsByPackageId;
19
+ private readonly Dictionary<string, WixBalPackageInfoSymbol> packageInfoSymbolsByPackageId = new Dictionary<string, WixBalPackageInfoSymbol>();
20
+ private readonly Dictionary<string, WixMbaPrereqInformationSymbol> prereqInfoSymbolsByPackageId = new Dictionary<string, WixMbaPrereqInformationSymbol>();
21
22
private enum WixDotNetCoreBootstrapperApplicationHostTheme
23
{
@@ -32,6 +33,13 @@ namespace WixToolset.Bal
33
Standard,
34
}
35
36
+ private enum WixInternalUIBootstrapperApplicationTheme
37
+ {
38
+ Unknown,
39
+ None,
40
+ Standard,
41
+ }
42
+
43
private enum WixStandardBootstrapperApplicationTheme
44
{
45
Unknown,
@@ -43,14 +51,6 @@ namespace WixToolset.Bal
51
RtfLicense,
52
}
53
46
- /// <summary>
47
- /// Instantiate a new BalCompiler.
48
- /// </summary>
49
- public BalCompiler()
50
- {
51
- this.prereqInfoSymbolsByPackageId = new Dictionary<string, WixMbaPrereqInformationSymbol>();
52
- }
53
-
54
public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/bal";
55
56
/// <summary>
@@ -83,6 +83,9 @@ namespace WixToolset.Bal
83
case "BootstrapperApplication":
84
switch (element.Name.LocalName)
85
{
86
+ case "WixInternalUIBootstrapperApplication":
87
+ this.ParseWixInternalUIBootstrapperApplicationElement(intermediate, section, element);
88
+ break;
89
case "WixStandardBootstrapperApplication":
90
this.ParseWixStandardBootstrapperApplicationElement(intermediate, section, element);
91
break;
@@ -113,7 +116,6 @@ namespace WixToolset.Bal
116
public override void ParseAttribute(Intermediate intermediate, IntermediateSection section, XElement parentElement, XAttribute attribute, IDictionary<string, string> context)
117
{
118
var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(parentElement);
116
- WixMbaPrereqInformationSymbol prereqInfo;
119
120
switch (parentElement.Name.LocalName)
121
{
@@ -137,42 +139,63 @@ namespace WixToolset.Bal
139
case "MsiPackage":
140
case "MspPackage":
141
var displayInternalUICondition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute);
140
- section.AddSymbol(new WixBalPackageInfoSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, packageId))
141
- {
142
- PackageId = packageId,
143
- DisplayInternalUICondition = displayInternalUICondition,
144
- });
142
+ var packageInfo = this.GetBalPackageInfoSymbol(section, sourceLineNumbers, packageId);
143
+ packageInfo.DisplayInternalUICondition = displayInternalUICondition;
144
break;
145
default:
146
this.ParseHelper.UnexpectedAttribute(parentElement, attribute);
147
break;
148
}
149
break;
151
- case "PrereqLicenseFile":
152
-
153
- if (!this.prereqInfoSymbolsByPackageId.TryGetValue(packageId, out prereqInfo))
150
+ case "PrimaryPackageType":
151
+ {
152
+ var primaryPackageType = BalPrimaryPackageType.None;
153
+ var primaryPackageTypeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute);
154
+ switch (primaryPackageTypeValue)
155
{
155
- // at the time the extension attribute is parsed, the compiler might not yet have
156
- // parsed the PrereqPackage attribute, so we need to get it directly from the parent element.
157
- var prereqPackage = parentElement.Attribute(this.Namespace + "PrereqPackage");
158
-
159
- if (null != prereqPackage && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, prereqPackage))
160
- {
161
- prereqInfo = section.AddSymbol(new WixMbaPrereqInformationSymbol(sourceLineNumbers)
162
- {
163
- PackageId = packageId,
164
- });
165
-
166
- this.prereqInfoSymbolsByPackageId.Add(packageId, prereqInfo);
167
- }
168
- else
169
- {
170
- this.Messaging.Write(BalErrors.AttributeRequiresPrereqPackage(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseFile"));
156
+ case "default":
157
+ primaryPackageType = BalPrimaryPackageType.Default;
158
+ break;
159
+ case "x86":
160
+ primaryPackageType = BalPrimaryPackageType.X86;
161
+ break;
162
+ case "x64":
163
+ primaryPackageType = BalPrimaryPackageType.X64;
164
+ break;
165
+ case "arm64":
166
+ primaryPackageType = BalPrimaryPackageType.ARM64;
167
+ break;
168
+ default:
169
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, parentElement.Name.LocalName, "PrimaryPackageType", primaryPackageTypeValue, "default", "x86", "x64", "arm64"));
170
break;
172
- }
171
}
172
175
- if (null != prereqInfo.LicenseUrl)
173
+ // at the time the extension attribute is parsed, the compiler might not yet have
174
+ // parsed the PrereqPackage attribute, so we need to get it directly from the parent element.
175
+ var prereqPackage = parentElement.Attribute(this.Namespace + "PrereqPackage");
176
+ var prereqInfo = this.GetMbaPrereqInformationSymbol(section, sourceLineNumbers, prereqPackage, packageId);
177
+ if (prereqInfo != null)
178
+ {
179
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithOtherAttribute(sourceLineNumbers, parentElement.Name.LocalName, "PrereqPackage", "yes", "PrimaryPackageType"));
180
+ }
181
+ else
182
+ {
183
+ var packageInfo = this.GetBalPackageInfoSymbol(section, sourceLineNumbers, packageId);
184
+ packageInfo.PrimaryPackageType = primaryPackageType;
185
+ }
186
+ break;
187
+ }
188
+ case "PrereqLicenseFile":
189
+ {
190
+ // at the time the extension attribute is parsed, the compiler might not yet have
191
+ // parsed the PrereqPackage attribute, so we need to get it directly from the parent element.
192
+ var prereqPackage = parentElement.Attribute(this.Namespace + "PrereqPackage");
193
+ var prereqInfo = this.GetMbaPrereqInformationSymbol(section, sourceLineNumbers, prereqPackage, packageId);
194
+ if (prereqInfo == null)
195
+ {
196
+ this.Messaging.Write(BalErrors.AttributeRequiresPrereqPackage(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseFile"));
197
+ }
198
+ else if (null != prereqInfo.LicenseUrl)
199
{
200
this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseFile", "PrereqLicenseUrl"));
201
}
@@ -181,31 +204,19 @@ namespace WixToolset.Bal
204
prereqInfo.LicenseFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute);
205
}
206
break;
207
+ }
208
case "PrereqLicenseUrl":
209
+ {
210
+ // at the time the extension attribute is parsed, the compiler might not yet have
211
+ // parsed the PrereqPackage attribute, so we need to get it directly from the parent element.
212
+ var prereqPackage = parentElement.Attribute(this.Namespace + "PrereqPackage");
213
+ var prereqInfo = this.GetMbaPrereqInformationSymbol(section, sourceLineNumbers, prereqPackage, packageId);
214
186
- if (!this.prereqInfoSymbolsByPackageId.TryGetValue(packageId, out prereqInfo))
215
+ if (prereqInfo == null)
216
{
188
- // at the time the extension attribute is parsed, the compiler might not yet have
189
- // parsed the PrereqPackage attribute, so we need to get it directly from the parent element.
190
- var prereqPackage = parentElement.Attribute(this.Namespace + "PrereqPackage");
191
-
192
- if (null != prereqPackage && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, prereqPackage))
193
- {
194
- prereqInfo = section.AddSymbol(new WixMbaPrereqInformationSymbol(sourceLineNumbers)
195
- {
196
- PackageId = packageId,
197
- });
198
-
199
- this.prereqInfoSymbolsByPackageId.Add(packageId, prereqInfo);
200
- }
201
- else
202
- {
203
- this.Messaging.Write(BalErrors.AttributeRequiresPrereqPackage(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseUrl"));
204
- break;
205
- }
217
+ this.Messaging.Write(BalErrors.AttributeRequiresPrereqPackage(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseUrl"));
218
}
207
-
208
- if (null != prereqInfo.LicenseFile)
219
+ else if (null != prereqInfo.LicenseFile)
220
{
221
this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, parentElement.Name.LocalName, "PrereqLicenseUrl", "PrereqLicenseFile"));
222
}
@@ -214,19 +225,9 @@ namespace WixToolset.Bal
225
prereqInfo.LicenseUrl = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute);
226
}
227
break;
228
+ }
229
case "PrereqPackage":
218
- if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attribute))
219
- {
220
- if (!this.prereqInfoSymbolsByPackageId.TryGetValue(packageId, out _))
221
- {
222
- prereqInfo = section.AddSymbol(new WixMbaPrereqInformationSymbol(sourceLineNumbers)
223
- {
224
- PackageId = packageId,
225
- });
226
-
227
- this.prereqInfoSymbolsByPackageId.Add(packageId, prereqInfo);
228
- }
229
- }
230
+ this.GetMbaPrereqInformationSymbol(section, sourceLineNumbers, attribute, packageId);
231
break;
232
default:
233
this.ParseHelper.UnexpectedAttribute(parentElement, attribute);
@@ -300,6 +301,41 @@ namespace WixToolset.Bal
301
}
302
}
303
304
+ private WixBalPackageInfoSymbol GetBalPackageInfoSymbol(IntermediateSection section, SourceLineNumber sourceLineNumbers, string packageId)
305
+ {
306
+ if (!this.packageInfoSymbolsByPackageId.TryGetValue(packageId, out var packageInfo))
307
+ {
308
+ packageInfo = section.AddSymbol(new WixBalPackageInfoSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, packageId))
309
+ {
310
+ PackageId = packageId,
311
+ });
312
+
313
+ this.packageInfoSymbolsByPackageId.Add(packageId, packageInfo);
314
+ }
315
+
316
+ return packageInfo;
317
+ }
318
+
319
+ private WixMbaPrereqInformationSymbol GetMbaPrereqInformationSymbol(IntermediateSection section, SourceLineNumber sourceLineNumbers, XAttribute prereqAttribute, string packageId)
320
+ {
321
+ WixMbaPrereqInformationSymbol prereqInfo = null;
322
+
323
+ if (prereqAttribute != null && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, prereqAttribute))
324
+ {
325
+ if (!this.prereqInfoSymbolsByPackageId.TryGetValue(packageId, out _))
326
+ {
327
+ prereqInfo = section.AddSymbol(new WixMbaPrereqInformationSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, packageId))
328
+ {
329
+ PackageId = packageId,
330
+ });
331
+
332
+ this.prereqInfoSymbolsByPackageId.Add(packageId, prereqInfo);
333
+ }
334
+ }
335
+
336
+ return prereqInfo;
337
+ }
338
+
339
/// <summary>
340
/// Parses a Condition element for Bundles.
341
/// </summary>
@@ -418,6 +454,101 @@ namespace WixToolset.Bal
454
}
455
}
456
457
+ private void ParseWixInternalUIBootstrapperApplicationElement(Intermediate intermediate, IntermediateSection section, XElement node)
458
+ {
459
+ var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(node);
460
+ WixInternalUIBootstrapperApplicationTheme? theme = null;
461
+ string themeFile = null;
462
+ string logoFile = null;
463
+ string localizationFile = null;
464
+
465
+ foreach (var attrib in node.Attributes())
466
+ {
467
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
468
+ {
469
+ switch (attrib.Name.LocalName)
470
+ {
471
+ case "LogoFile":
472
+ logoFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
473
+ break;
474
+ case "ThemeFile":
475
+ themeFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
476
+ break;
477
+ case "LocalizationFile":
478
+ localizationFile = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
479
+ break;
480
+ case "Theme":
481
+ var themeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
482
+ switch (themeValue)
483
+ {
484
+ case "none":
485
+ theme = WixInternalUIBootstrapperApplicationTheme.None;
486
+ break;
487
+ case "standard":
488
+ theme = WixInternalUIBootstrapperApplicationTheme.Standard;
489
+ break;
490
+ default:
491
+ this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, "Theme", themeValue, "none", "standard"));
492
+ theme = WixInternalUIBootstrapperApplicationTheme.Unknown;
493
+ break;
494
+ }
495
+ break;
496
+ default:
497
+ this.ParseHelper.UnexpectedAttribute(node, attrib);
498
+ break;
499
+ }
500
+ }
501
+ else
502
+ {
503
+ this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, node, attrib);
504
+ }
505
+ }
506
+
507
+ this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, node);
508
+
509
+ if (!theme.HasValue)
510
+ {
511
+ theme = WixInternalUIBootstrapperApplicationTheme.Standard;
512
+ }
513
+
514
+ if (!this.Messaging.EncounteredError)
515
+ {
516
+ if (!String.IsNullOrEmpty(logoFile))
517
+ {
518
+ section.AddSymbol(new WixVariableSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, "WixIuibaLogo"))
519
+ {
520
+ Value = logoFile,
521
+ });
522
+ }
523
+
524
+ if (!String.IsNullOrEmpty(themeFile))
525
+ {
526
+ section.AddSymbol(new WixVariableSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, "WixIuibaThemeXml"))
527
+ {
528
+ Value = themeFile,
529
+ });
530
+ }
531
+
532
+ if (!String.IsNullOrEmpty(localizationFile))
533
+ {
534
+ section.AddSymbol(new WixVariableSymbol(sourceLineNumbers, new Identifier(AccessModifier.Global, "WixIuibaThemeWxl"))
535
+ {
536
+ Value = localizationFile,
537
+ });
538
+ }
539
+
540
+ var baId = "WixInternalUIBootstrapperApplication";
541
+ switch (theme)
542
+ {
543
+ case WixInternalUIBootstrapperApplicationTheme.Standard:
544
+ baId = "WixInternalUIBootstrapperApplication.Standard";
545
+ break;
546
+ }
547
+
548
+ this.CreateBARef(section, sourceLineNumbers, node, baId);
549
+ }
550
+ }
551
+
552
/// <summary>
553
/// Parses a WixStandardBootstrapperApplication element for Bundles.
554
/// </summary>
src/ext/Bal/wixext/BalErrors.cs
+48
@@ -18,11 +18,41 @@ namespace WixToolset.Bal
18
return Message(sourceLineNumbers, Ids.BAFunctionsPayloadRequiredInUXContainer, "The BAFunctions DLL Payload element must be located inside the BootstrapperApplication container.");
19
}
20
21
+ public static Message IuibaNonMsiPrimaryPackage(SourceLineNumber sourceLineNumbers)
22
+ {
23
+ return Message(sourceLineNumbers, Ids.IuibaNonMsiPrimaryPackage, "When using WixInternalUIBootstrapperApplication, each primary package must be an MsiPackage.");
24
+ }
25
+
26
+ public static Message IuibaNonPermanentNonPrimaryPackage(SourceLineNumber sourceLineNumbers)
27
+ {
28
+ return Message(sourceLineNumbers, Ids.IuibaNonPermanentNonPrimaryPackage, "When using WixInternalUIBootstrapperApplication, packages must either be non-permanent and have the bal:PrimaryPackageType attribute, or be permanent and have the bal:PrereqPackage attribute set to 'yes'.");
29
+ }
30
+
31
+ public static Message IuibaNonPermanentPrereqPackage(SourceLineNumber sourceLineNumbers)
32
+ {
33
+ return Message(sourceLineNumbers, Ids.IuibaNonPermanentPrereqPackage, "When using WixInternalUIBootstrapperApplication and bal:PrereqPackage is set to 'yes', the package must be permanent.");
34
+ }
35
+
36
+ public static Message IuibaPermanentPrimaryPackageType(SourceLineNumber sourceLineNumbers)
37
+ {
38
+ return Message(sourceLineNumbers, Ids.IuibaPermanentPrimaryPackageType, "When using WixInternalUIBootstrapperApplication, packages with the bal:PrimaryPackageType attribute must not be permanent.");
39
+ }
40
+
41
+ public static Message IuibaPrimaryPackageEnableFeatureSelection(SourceLineNumber sourceLineNumbers)
42
+ {
43
+ return Message(sourceLineNumbers, Ids.IuibaPrimaryPackageEnableFeatureSelection, "When using WixInternalUIBootstrapperApplication, primary packages must not have feature selection enabled because it interferes with the user selecting feature through the MSI UI.");
44
+ }
45
+
46
public static Message MissingDNCPrereq()
47
{
48
return Message(null, Ids.MissingDNCPrereq, "There must be at least one PrereqPackage when using the DotNetCoreBootstrapperApplicationHost with SelfContainedDeployment set to \"no\".");
49
}
50
51
+ public static Message MissingIUIPrimaryPackage()
52
+ {
53
+ return Message(null, Ids.MissingIUIPrimaryPackage, "When using WixInternalUIBootstrapperApplication, there must be one package with bal:PrimaryPackageType=\"default\".");
54
+ }
55
+
56
public static Message MissingMBAPrereq()
57
{
58
return Message(null, Ids.MissingMBAPrereq, "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.");
@@ -38,6 +68,16 @@ namespace WixToolset.Bal
68
return Message(sourceLineNumbers, Ids.MultiplePrereqLicenses, "There may only be one package in the bundle that has either the PrereqLicenseFile attribute or the PrereqLicenseUrl attribute.");
69
}
70
71
+ public static Message MultiplePrimaryPackageType(SourceLineNumber sourceLineNumbers, string primaryPackageType)
72
+ {
73
+ return Message(sourceLineNumbers, Ids.MultiplePrimaryPackageType, "There may only be one package in the bundle with PrimaryPackageType of '{0}'.", primaryPackageType);
74
+ }
75
+
76
+ public static Message MultiplePrimaryPackageType2(SourceLineNumber sourceLineNumbers)
77
+ {
78
+ return Message(sourceLineNumbers, Ids.MultiplePrimaryPackageType2, "The location of the package related to the previous error.");
79
+ }
80
+
81
public static Message NonUpperCaseOverridableVariable(SourceLineNumber sourceLineNumbers, string name, string expectedName)
82
{
83
return Message(sourceLineNumbers, Ids.NonUpperCaseOverridableVariable, "Overridable variable '{0}' must be '{1}' with Bundle/@CommandLineVariables value 'upperCase'.", name, expectedName);
@@ -62,6 +102,14 @@ namespace WixToolset.Bal
102
BAFunctionsPayloadRequiredInUXContainer = 6805,
103
MissingDNCPrereq = 6806,
104
NonUpperCaseOverridableVariable = 6807,
105
+ MissingIUIPrimaryPackage = 6808,
106
+ MultiplePrimaryPackageType = 6809,
107
+ MultiplePrimaryPackageType2 = 6810,
108
+ IuibaNonPermanentNonPrimaryPackage = 6811,
109
+ IuibaNonPermanentPrereqPackage = 6812,
110
+ IuibaPermanentPrimaryPackageType = 6813,
111
+ IuibaNonMsiPrimaryPackage = 6814,
112
+ IuibaPrimaryPackageEnableFeatureSelection = 6815,
113
}
114
}
115
}
src/ext/Bal/wixext/BalWarnings.cs
+24
@@ -8,6 +8,26 @@ namespace WixToolset.Bal
8
9
public static class BalWarnings
10
{
11
+ public static Message IuibaForceCachePrereq(SourceLineNumber sourceLineNumbers)
12
+ {
13
+ return Message(sourceLineNumbers, Ids.IuibaForceCachePrereq, "WixInternalUIBootstrapperApplication does not support the value of 'force' for Cache on prereq packages. Prereq packages are only cached when they need to be installed.");
14
+ }
15
+
16
+ public static Message IuibaPrereqPackageAfterPrimaryPackage(SourceLineNumber sourceLineNumbers)
17
+ {
18
+ return Message(sourceLineNumbers, Ids.IuibaPrereqPackageAfterPrimaryPackage, "When using WixInternalUIBootstrapperApplication, all prereq packages should be before the primary package in the chain. The prereq packages are always installed before the primary package.");
19
+ }
20
+
21
+ public static Message IuibaPrimaryPackageDisplayInternalUICondition(SourceLineNumber sourceLineNumbers)
22
+ {
23
+ return Message(sourceLineNumbers, Ids.IuibaPrimaryPackageDisplayInternalUICondition, "WixInternalUIBootstrapperApplication ignores DisplayInternalUICondition for the primary package so that the MSI UI is always shown.");
24
+ }
25
+
26
+ public static Message IuibaPrimaryPackageInstallCondition(SourceLineNumber sourceLineNumbers)
27
+ {
28
+ return Message(sourceLineNumbers, Ids.IuibaPrimaryPackageInstallCondition, "WixInternalUIBootstrapperApplication ignores InstallCondition for the primary package so that the MSI UI is always shown.");
29
+ }
30
+
31
public static Message UnmarkedBAFunctionsDLL(SourceLineNumber sourceLineNumbers)
32
{
33
return Message(sourceLineNumbers, Ids.UnmarkedBAFunctionsDLL, "WixStandardBootstrapperApplication doesn't automatically load BAFunctions.dll. Use the bal:BAFunctions attribute to indicate that it should be loaded.");
@@ -26,6 +46,10 @@ namespace WixToolset.Bal
46
public enum Ids
47
{
48
UnmarkedBAFunctionsDLL = 6501,
49
+ IuibaForceCachePrereq = 6502,
50
+ IuibaPrimaryPackageInstallCondition = 6503,
51
+ IuibaPrimaryPackageDisplayInternalUICondition = 6504,
52
+ IuibaPrereqPackageAfterPrimaryPackage = 6505,
53
}
54
}
55
}
src/ext/Bal/wixext/Symbols/WixBalPackageInfoSymbol.cs
+17
@@ -13,6 +13,7 @@ namespace WixToolset.Bal
13
{
14
new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.PackageId), IntermediateFieldType.String),
15
new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.DisplayInternalUICondition), IntermediateFieldType.String),
16
+ new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.PrimaryPackageType), IntermediateFieldType.Number),
17
},
18
typeof(WixBalPackageInfoSymbol));
19
}
@@ -26,6 +27,16 @@ namespace WixToolset.Bal.Symbols
27
{
28
PackageId,
29
DisplayInternalUICondition,
30
+ PrimaryPackageType,
31
+ }
32
+
33
+ public enum BalPrimaryPackageType
34
+ {
35
+ None,
36
+ Default,
37
+ X86,
38
+ X64,
39
+ ARM64,
40
}
41
42
public class WixBalPackageInfoSymbol : IntermediateSymbol
@@ -51,5 +62,11 @@ namespace WixToolset.Bal.Symbols
62
get => this.Fields[(int)WixBalPackageInfoSymbolFields.DisplayInternalUICondition].AsString();
63
set => this.Set((int)WixBalPackageInfoSymbolFields.DisplayInternalUICondition, value);
64
}
65
+
66
+ public BalPrimaryPackageType PrimaryPackageType
67
+ {
68
+ get => (BalPrimaryPackageType)this.Fields[(int)WixBalPackageInfoSymbolFields.PrimaryPackageType].AsNumber();
69
+ set => this.Set((int)WixBalPackageInfoSymbolFields.PrimaryPackageType, (int)value);
70
+ }
71
}
72
}
src/ext/Bal/wixiuiba/WixInternalUIBootstrapperApplication.cpp
new
+918
@@ -0,0 +1,918 @@
1
+// 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.
2
+
3
+#include "precomp.h"
4
+#include "BalBaseBootstrapperApplicationProc.h"
5
+#include "BalBaseBootstrapperApplication.h"
6
+
7
+static const LPCWSTR WIXIUIBA_WINDOW_CLASS = L"WixInternalUIBA";
8
+
9
+enum WM_WIXIUIBA
10
+{
11
+ WM_WIXIUIBA_DETECT_PACKAGES = WM_APP + 100,
12
+ WM_WIXIUIBA_PLAN_PACKAGES,
13
+ WM_WIXIUIBA_APPLY_PACKAGES,
14
+ WM_WIXIUIBA_DETECT_FOR_CLEANUP,
15
+ WM_WIXIUIBA_PLAN_PACKAGES_FOR_CLEANUP,
16
+};
17
+
18
+
19
+class CWixInternalUIBootstrapperApplication : public CBalBaseBootstrapperApplication
20
+{
21
+public: // IBootstrapperApplication
22
+ virtual STDMETHODIMP OnStartup()
23
+ {
24
+ HRESULT hr = S_OK;
25
+ DWORD dwUIThreadId = 0;
26
+
27
+ // create UI thread
28
+ m_hUiThread = ::CreateThread(NULL, 0, UiThreadProc, this, 0, &dwUIThreadId);
29
+ if (!m_hUiThread)
30
+ {
31
+ BalExitWithLastError(hr, "Failed to create UI thread.");
32
+ }
33
+
34
+ LExit:
35
+ return hr;
36
+ }
37
+
38
+
39
+ virtual STDMETHODIMP OnShutdown(
40
+ __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction
41
+ )
42
+ {
43
+ // wait for UI thread to terminate
44
+ if (m_hUiThread)
45
+ {
46
+ ::WaitForSingleObject(m_hUiThread, INFINITE);
47
+ ReleaseHandle(m_hUiThread);
48
+ }
49
+
50
+ if (m_fFailedToLoadPackage)
51
+ {
52
+ Assert(FAILED(m_hrFinal));
53
+ m_pPrereqData->hrFatalError = m_hrFinal;
54
+ BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load primary package as the BA. The bootstrapper application will be reloaded to show the error.");
55
+ *pAction = BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER;
56
+ }
57
+
58
+ return S_OK;
59
+ }
60
+
61
+
62
+ virtual STDMETHODIMP OnDetectPackageComplete(
63
+ __in_z LPCWSTR wzPackageId,
64
+ __in HRESULT hrStatus,
65
+ __in BOOTSTRAPPER_PACKAGE_STATE state,
66
+ __in BOOL fCached
67
+ )
68
+ {
69
+ BAL_INFO_PACKAGE* pPackage = NULL;
70
+
71
+ if (SUCCEEDED(hrStatus) && SUCCEEDED(BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage)) &&
72
+ BAL_INFO_PRIMARY_PACKAGE_TYPE_DEFAULT == pPackage->primaryPackageType)
73
+ {
74
+ BOOL fInstalled = BOOTSTRAPPER_PACKAGE_STATE_ABSENT < state;
75
+
76
+ // Maybe modify the action state if the primary package is or is not already installed.
77
+ if (fInstalled && BOOTSTRAPPER_ACTION_INSTALL == m_command.action)
78
+ {
79
+ m_command.action = BOOTSTRAPPER_ACTION_MODIFY;
80
+ }
81
+ else if (!fInstalled && (BOOTSTRAPPER_ACTION_MODIFY == m_command.action || BOOTSTRAPPER_ACTION_REPAIR == m_command.action))
82
+ {
83
+ m_command.action = BOOTSTRAPPER_ACTION_INSTALL;
84
+ }
85
+
86
+ if (m_fApplied && !fInstalled && fCached)
87
+ {
88
+ m_fAutomaticRemoval = TRUE;
89
+ }
90
+ }
91
+
92
+ return __super::OnDetectPackageComplete(wzPackageId, hrStatus, state, fCached);
93
+ }
94
+
95
+
96
+ virtual STDMETHODIMP OnDetectComplete(
97
+ __in HRESULT hrStatus,
98
+ __in BOOL fEligibleForCleanup
99
+ )
100
+ {
101
+ if (m_fAutomaticRemoval && SUCCEEDED(hrStatus))
102
+ {
103
+ ::PostMessageW(m_hWnd, WM_WIXIUIBA_PLAN_PACKAGES_FOR_CLEANUP, 0, BOOTSTRAPPER_ACTION_UNINSTALL);
104
+ ExitFunction();
105
+ }
106
+ else if (m_fApplied)
107
+ {
108
+ ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);
109
+ ExitFunction();
110
+ }
111
+
112
+ // If we're performing an action that modifies machine state then evaluate conditions.
113
+ BOOL fEvaluateConditions = SUCCEEDED(hrStatus) &&
114
+ (BOOTSTRAPPER_ACTION_LAYOUT < m_command.action && BOOTSTRAPPER_ACTION_UPDATE_REPLACE > m_command.action);
115
+
116
+ if (fEvaluateConditions)
117
+ {
118
+ hrStatus = EvaluateConditions();
119
+ }
120
+
121
+ if (SUCCEEDED(hrStatus))
122
+ {
123
+ ::PostMessageW(m_hWnd, WM_WIXIUIBA_PLAN_PACKAGES, 0, m_command.action);
124
+ }
125
+ else
126
+ {
127
+ SetLoadPackageFailure(hrStatus);
128
+ }
129
+
130
+ LExit:
131
+ return __super::OnDetectComplete(hrStatus, fEligibleForCleanup);
132
+ }
133
+
134
+
135
+ virtual STDMETHODIMP OnPlanPackageBegin(
136
+ __in_z LPCWSTR wzPackageId,
137
+ __in BOOTSTRAPPER_PACKAGE_STATE state,
138
+ __in BOOL fCached,
139
+ __in BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition,
140
+ __in BOOTSTRAPPER_PACKAGE_CONDITION_RESULT repairCondition,
141
+ __in BOOTSTRAPPER_REQUEST_STATE recommendedState,
142
+ __in BOOTSTRAPPER_CACHE_TYPE recommendedCacheType,
143
+ __inout BOOTSTRAPPER_REQUEST_STATE* pRequestState,
144
+ __inout BOOTSTRAPPER_CACHE_TYPE* pRequestedCacheType,
145
+ __inout BOOL* pfCancel
146
+ )
147
+ {
148
+ HRESULT hr = S_OK;
149
+ BAL_INFO_PACKAGE* pPackage = NULL;
150
+
151
+ hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
152
+ if (FAILED(hr))
153
+ {
154
+ // Non-chain package, keep default.
155
+ }
156
+ else if (BAL_INFO_PRIMARY_PACKAGE_TYPE_DEFAULT != pPackage->primaryPackageType)
157
+ {
158
+ // Only the primary package should be cached or executed.
159
+ if (BOOTSTRAPPER_CACHE_TYPE_FORCE == *pRequestedCacheType)
160
+ {
161
+ *pRequestedCacheType = BOOTSTRAPPER_CACHE_TYPE_KEEP;
162
+ }
163
+
164
+ *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
165
+ }
166
+ else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display && !m_fAutomaticRemoval)
167
+ {
168
+ // Make sure the MSI UI is shown regardless of the current state of the package.
169
+ *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR;
170
+ }
171
+
172
+ return __super::OnPlanPackageBegin(wzPackageId, state, fCached, installCondition, repairCondition, recommendedState, recommendedCacheType, pRequestState, pRequestedCacheType, pfCancel);
173
+ }
174
+
175
+
176
+ virtual STDMETHODIMP OnPlanMsiPackage(
177
+ __in_z LPCWSTR wzPackageId,
178
+ __in BOOL fExecute,
179
+ __in BOOTSTRAPPER_ACTION_STATE action,
180
+ __in BOOTSTRAPPER_MSI_FILE_VERSIONING recommendedFileVersioning,
181
+ __inout BOOL* pfCancel,
182
+ __inout BURN_MSI_PROPERTY* pActionMsiProperty,
183
+ __inout INSTALLUILEVEL* pUiLevel,
184
+ __inout BOOL* pfDisableExternalUiHandler,
185
+ __inout BOOTSTRAPPER_MSI_FILE_VERSIONING* pFileVersioning
186
+ )
187
+ {
188
+ INSTALLUILEVEL uiLevel = INSTALLUILEVEL_NOCHANGE;
189
+
190
+ if (m_fAutomaticRemoval)
191
+ {
192
+ ExitFunction();
193
+ }
194
+
195
+ switch (m_command.display)
196
+ {
197
+ case BOOTSTRAPPER_DISPLAY_FULL:
198
+ uiLevel = INSTALLUILEVEL_FULL;
199
+ break;
200
+
201
+ case BOOTSTRAPPER_DISPLAY_PASSIVE:
202
+ uiLevel = INSTALLUILEVEL_REDUCED;
203
+ break;
204
+ }
205
+
206
+ if (INSTALLUILEVEL_NOCHANGE != uiLevel)
207
+ {
208
+ *pUiLevel = uiLevel;
209
+ }
210
+
211
+ *pActionMsiProperty = BURN_MSI_PROPERTY_NONE;
212
+ *pfDisableExternalUiHandler = TRUE;
213
+
214
+ LExit:
215
+ return __super::OnPlanMsiPackage(wzPackageId, fExecute, action, recommendedFileVersioning, pfCancel, pActionMsiProperty, pUiLevel, pfDisableExternalUiHandler, pFileVersioning);
216
+ }
217
+
218
+
219
+ virtual STDMETHODIMP OnPlanComplete(
220
+ __in HRESULT hrStatus
221
+ )
222
+ {
223
+ if (SUCCEEDED(hrStatus))
224
+ {
225
+ ::PostMessageW(m_hWnd, WM_WIXIUIBA_APPLY_PACKAGES, 0, 0);
226
+ }
227
+ else if (m_fAutomaticRemoval)
228
+ {
229
+ ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);
230
+ }
231
+ else
232
+ {
233
+ SetLoadPackageFailure(hrStatus);
234
+ }
235
+
236
+ return __super::OnPlanComplete(hrStatus);
237
+ }
238
+
239
+
240
+ virtual STDMETHODIMP OnApplyBegin(
241
+ __in DWORD dwPhaseCount,
242
+ __inout BOOL* pfCancel
243
+ )
244
+ {
245
+ m_fApplying = TRUE;
246
+ return __super::OnApplyBegin(dwPhaseCount, pfCancel);
247
+ }
248
+
249
+
250
+ virtual STDMETHODIMP OnCacheComplete(
251
+ __in HRESULT hrStatus
252
+ )
253
+ {
254
+ if (FAILED(hrStatus) && !m_fAutomaticRemoval)
255
+ {
256
+ SetLoadPackageFailure(hrStatus);
257
+ }
258
+
259
+ return __super::OnCacheComplete(hrStatus);
260
+ }
261
+
262
+
263
+ virtual STDMETHODIMP OnExecuteBegin(
264
+ __in DWORD cExecutingPackages,
265
+ __in BOOL* pfCancel
266
+ )
267
+ {
268
+ m_pEngine->CloseSplashScreen();
269
+
270
+ return __super::OnExecuteBegin(cExecutingPackages, pfCancel);
271
+ }
272
+
273
+
274
+ virtual STDMETHODIMP OnApplyComplete(
275
+ __in HRESULT hrStatus,
276
+ __in BOOTSTRAPPER_APPLY_RESTART restart,
277
+ __in BOOTSTRAPPER_APPLYCOMPLETE_ACTION recommendation,
278
+ __inout BOOTSTRAPPER_APPLYCOMPLETE_ACTION* pAction
279
+ )
280
+ {
281
+ HRESULT hr = __super::OnApplyComplete(hrStatus, restart, recommendation, pAction);
282
+
283
+ *pAction = BOOTSTRAPPER_APPLYCOMPLETE_ACTION_NONE;
284
+ m_fApplying = FALSE;
285
+
286
+ if (m_fAutomaticRemoval)
287
+ {
288
+ ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);
289
+ }
290
+ else
291
+ {
292
+ m_restartResult = restart; // remember the restart result so we return the correct error code.
293
+ m_fApplied = TRUE;
294
+
295
+ if (FAILED(hrStatus))
296
+ {
297
+ m_hrFinal = hrStatus;
298
+ }
299
+
300
+ ::PostMessageW(m_hWnd, WM_WIXIUIBA_DETECT_FOR_CLEANUP, 0, 0);
301
+ }
302
+
303
+ return hr;
304
+ }
305
+
306
+
307
+public: //CBalBaseBootstrapperApplication
308
+ virtual STDMETHODIMP Initialize(
309
+ __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs
310
+ )
311
+ {
312
+ HRESULT hr = S_OK;
313
+
314
+ hr = __super::Initialize(pCreateArgs);
315
+ BalExitOnFailure(hr, "CBalBaseBootstrapperApplication initialization failed.");
316
+
317
+ memcpy_s(&m_command, sizeof(m_command), pCreateArgs->pCommand, sizeof(BOOTSTRAPPER_COMMAND));
318
+ memcpy_s(&m_createArgs, sizeof(m_createArgs), pCreateArgs, sizeof(BOOTSTRAPPER_CREATE_ARGS));
319
+ m_createArgs.pCommand = &m_command;
320
+
321
+ LExit:
322
+ return hr;
323
+ }
324
+
325
+ void Uninitialize(
326
+ __in const BOOTSTRAPPER_DESTROY_ARGS* /*pArgs*/,
327
+ __in BOOTSTRAPPER_DESTROY_RESULTS* /*pResults*/
328
+ )
329
+ {
330
+ }
331
+
332
+
333
+private:
334
+ //
335
+ // UiThreadProc - entrypoint for UI thread.
336
+ //
337
+ static DWORD WINAPI UiThreadProc(
338
+ __in LPVOID pvContext
339
+ )
340
+ {
341
+ HRESULT hr = S_OK;
342
+ CWixInternalUIBootstrapperApplication* pThis = (CWixInternalUIBootstrapperApplication*)pvContext;
343
+ BOOL fComInitialized = FALSE;
344
+ BOOL fRet = FALSE;
345
+ MSG msg = { };
346
+ DWORD dwQuit = 0;
347
+
348
+ // Initialize COM and theme.
349
+ hr = ::CoInitialize(NULL);
350
+ BalExitOnFailure(hr, "Failed to initialize COM.");
351
+ fComInitialized = TRUE;
352
+
353
+ hr = pThis->InitializeData();
354
+ BalExitOnFailure(hr, "Failed to initialize data in bootstrapper application.");
355
+
356
+ // Create main window.
357
+ hr = pThis->CreateMainWindow();
358
+ BalExitOnFailure(hr, "Failed to create main window.");
359
+
360
+ ::PostMessageW(pThis->m_hWnd, WM_WIXIUIBA_DETECT_PACKAGES, 0, 0);
361
+
362
+ // message pump
363
+ while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
364
+ {
365
+ if (-1 == fRet)
366
+ {
367
+ hr = E_UNEXPECTED;
368
+ BalExitOnFailure(hr, "Unexpected return value from message pump.");
369
+ }
370
+ else if (!::IsDialogMessageW(pThis->m_hWnd, &msg))
371
+ {
372
+ ::TranslateMessage(&msg);
373
+ ::DispatchMessageW(&msg);
374
+ }
375
+ }
376
+
377
+ // Succeeded thus far, check to see if anything went wrong while actually
378
+ // executing changes.
379
+ if (FAILED(pThis->m_hrFinal))
380
+ {
381
+ hr = pThis->m_hrFinal;
382
+ }
383
+ else if (pThis->CheckCanceled())
384
+ {
385
+ hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
386
+ }
387
+
388
+ LExit:
389
+ // destroy main window
390
+ pThis->DestroyMainWindow();
391
+
392
+ if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult)
393
+ {
394
+ dwQuit = ERROR_SUCCESS_REBOOT_INITIATED;
395
+ }
396
+ else if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == pThis->m_restartResult)
397
+ {
398
+ dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED;
399
+ }
400
+ else if (SEVERITY_ERROR == HRESULT_SEVERITY(hr) && FACILITY_WIN32 == HRESULT_FACILITY(hr))
401
+ {
402
+ // Convert Win32 HRESULTs back to the error code.
403
+ dwQuit = HRESULT_CODE(hr);
404
+ }
405
+ else
406
+ {
407
+ dwQuit = hr;
408
+ }
409
+
410
+ // initiate engine shutdown
411
+ pThis->m_pEngine->Quit(dwQuit);
412
+
413
+ // uninitialize COM
414
+ if (fComInitialized)
415
+ {
416
+ ::CoUninitialize();
417
+ }
418
+
419
+ return hr;
420
+ }
421
+
422
+
423
+ //
424
+ // InitializeData - initializes all the package and prerequisite information.
425
+ //
426
+ HRESULT InitializeData()
427
+ {
428
+ HRESULT hr = S_OK;
429
+ IXMLDOMDocument* pixdManifest = NULL;
430
+
431
+ hr = BalManifestLoad(m_hModule, &pixdManifest);
432
+ BalExitOnFailure(hr, "Failed to load bootstrapper application manifest.");
433
+
434
+ hr = BalInfoParseFromXml(&m_Bundle, pixdManifest);
435
+ BalExitOnFailure(hr, "Failed to load bundle information.");
436
+
437
+ hr = EnsureSinglePrimaryPackage();
438
+ BalExitOnFailure(hr, "Failed to ensure single primary package.");
439
+
440
+ hr = ProcessCommandLine();
441
+ ExitOnFailure(hr, "Unknown commandline parameters.");
442
+
443
+ hr = BalConditionsParseFromXml(&m_Conditions, pixdManifest, NULL);
444
+ BalExitOnFailure(hr, "Failed to load conditions from XML.");
445
+
446
+ LExit:
447
+ ReleaseObject(pixdManifest);
448
+
449
+ return hr;
450
+ }
451
+
452
+
453
+ //
454
+ // ProcessCommandLine - process the provided command line arguments.
455
+ //
456
+ HRESULT ProcessCommandLine()
457
+ {
458
+ HRESULT hr = S_OK;
459
+ int argc = 0;
460
+ LPWSTR* argv = NULL;
461
+
462
+ argc = m_BalInfoCommand.cUnknownArgs;
463
+ argv = m_BalInfoCommand.rgUnknownArgs;
464
+
465
+ for (int i = 0; i < argc; ++i)
466
+ {
467
+ BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Ignoring unknown argument: %ls", argv[i]);
468
+ }
469
+
470
+ hr = BalSetOverridableVariablesFromEngine(&m_Bundle.overridableVariables, &m_BalInfoCommand, m_pEngine);
471
+ BalExitOnFailure(hr, "Failed to set overridable variables from the command line.");
472
+
473
+ LExit:
474
+ return hr;
475
+ }
476
+
477
+ HRESULT EnsureSinglePrimaryPackage()
478
+ {
479
+ HRESULT hr = S_OK;
480
+ BAL_INFO_PACKAGE* pDefaultPackage = NULL;
481
+ BOOL fPrimaryArchSpecific = FALSE;
482
+ USHORT usNativeMachine = 0;
483
+ BAL_INFO_PRIMARY_PACKAGE_TYPE nativeType = BAL_INFO_PRIMARY_PACKAGE_TYPE_NONE;
484
+
485
+ hr = ProcNativeMachine(::GetCurrentProcess(), &usNativeMachine);
486
+ BalExitOnFailure(hr, "Failed to get native machine value.");
487
+
488
+ if (S_FALSE != hr)
489
+ {
490
+ switch (usNativeMachine)
491
+ {
492
+ case IMAGE_FILE_MACHINE_I386:
493
+ nativeType = BAL_INFO_PRIMARY_PACKAGE_TYPE_X86;
494
+ break;
495
+ case IMAGE_FILE_MACHINE_AMD64:
496
+ nativeType = BAL_INFO_PRIMARY_PACKAGE_TYPE_X64;
497
+ break;
498
+ case IMAGE_FILE_MACHINE_ARM64:
499
+ nativeType = BAL_INFO_PRIMARY_PACKAGE_TYPE_ARM64;
500
+ break;
501
+ }
502
+ }
503
+ else
504
+ {
505
+#if !defined(_WIN64)
506
+ BOOL fIsWow64 = FALSE;
507
+
508
+ ProcWow64(::GetCurrentProcess(), &fIsWow64);
509
+ if (!fIsWow64)
510
+ {
511
+ nativeType = BAL_INFO_PRIMARY_PACKAGE_TYPE_X86;
512
+ }
513
+ else
514
+#endif
515
+ {
516
+ nativeType = BAL_INFO_PRIMARY_PACKAGE_TYPE_X64;
517
+ }
518
+ }
519
+
520
+ for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
521
+ {
522
+ BAL_INFO_PACKAGE* pPackage = m_Bundle.packages.rgPackages + i;
523
+
524
+ if (BAL_INFO_PRIMARY_PACKAGE_TYPE_NONE == pPackage->primaryPackageType)
525
+ {
526
+ // Skip.
527
+ }
528
+ else if (nativeType == pPackage->primaryPackageType)
529
+ {
530
+ if (fPrimaryArchSpecific)
531
+ {
532
+ BalExitWithRootFailure(hr, E_INVALIDDATA, "Bundle contains multiple primary packages for same architecture: %u.", nativeType);
533
+ }
534
+
535
+ pPackage->primaryPackageType = BAL_INFO_PRIMARY_PACKAGE_TYPE_DEFAULT;
536
+ fPrimaryArchSpecific = TRUE;
537
+ }
538
+ else if (BAL_INFO_PRIMARY_PACKAGE_TYPE_DEFAULT == pPackage->primaryPackageType)
539
+ {
540
+ if (pDefaultPackage)
541
+ {
542
+ BalExitWithRootFailure(hr, E_INVALIDDATA, "Bundle contains multiple default primary packages.");
543
+ }
544
+
545
+ pDefaultPackage = pPackage;
546
+ }
547
+ }
548
+
549
+ BalExitOnNull(pDefaultPackage, hr, E_INVALIDSTATE, "Bundle did not contain default primary package.");
550
+
551
+ if (fPrimaryArchSpecific)
552
+ {
553
+ pDefaultPackage->primaryPackageType = BAL_INFO_PRIMARY_PACKAGE_TYPE_NONE;
554
+ }
555
+
556
+ LExit:
557
+ return hr;
558
+ }
559
+
560
+
561
+ //
562
+ // CreateMainWindow - creates the main install window.
563
+ //
564
+ HRESULT CreateMainWindow()
565
+ {
566
+ HRESULT hr = S_OK;
567
+ WNDCLASSW wc = { };
568
+ DWORD dwWindowStyle = WS_POPUP;
569
+
570
+ wc.lpfnWndProc = CWixInternalUIBootstrapperApplication::WndProc;
571
+ wc.hInstance = m_hModule;
572
+ wc.lpszClassName = WIXIUIBA_WINDOW_CLASS;
573
+
574
+ if (!::RegisterClassW(&wc))
575
+ {
576
+ ExitWithLastError(hr, "Failed to register window.");
577
+ }
578
+
579
+ m_fRegistered = TRUE;
580
+
581
+ // If the UI should be visible, allow it to be visible and activated so we are the foreground window.
582
+ // This allows the UAC prompt and MSI UI to automatically be activated.
583
+ if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)
584
+ {
585
+ dwWindowStyle |= WS_VISIBLE;
586
+ }
587
+
588
+ m_hWnd = ::CreateWindowExW(WS_EX_TOOLWINDOW, wc.lpszClassName, NULL, dwWindowStyle, 0, 0, 0, 0, HWND_DESKTOP, NULL, m_hModule, this);
589
+ ExitOnNullWithLastError(m_hWnd, hr, "Failed to create window.");
590
+
591
+ LExit:
592
+ return hr;
593
+ }
594
+
595
+ //
596
+ // DestroyMainWindow - clean up all the window registration.
597
+ //
598
+ void DestroyMainWindow()
599
+ {
600
+ if (::IsWindow(m_hWnd))
601
+ {
602
+ ::DestroyWindow(m_hWnd);
603
+ m_hWnd = NULL;
604
+ }
605
+
606
+ if (m_fRegistered)
607
+ {
608
+ ::UnregisterClassW(WIXIUIBA_WINDOW_CLASS, m_hModule);
609
+ m_fRegistered = FALSE;
610
+ }
611
+ }
612
+
613
+ //
614
+ // WndProc - standard windows message handler.
615
+ //
616
+ static LRESULT CALLBACK WndProc(
617
+ __in HWND hWnd,
618
+ __in UINT uMsg,
619
+ __in WPARAM wParam,
620
+ __in LPARAM lParam
621
+ )
622
+ {
623
+#pragma warning(suppress:4312)
624
+ CWixInternalUIBootstrapperApplication* pBA = reinterpret_cast<CWixInternalUIBootstrapperApplication*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
625
+
626
+ switch (uMsg)
627
+ {
628
+ case WM_NCCREATE:
629
+ {
630
+ LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
631
+ pBA = reinterpret_cast<CWixInternalUIBootstrapperApplication*>(lpcs->lpCreateParams);
632
+#pragma warning(suppress:4244)
633
+ ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pBA));
634
+ }
635
+ break;
636
+
637
+ case WM_NCDESTROY:
638
+ {
639
+ LRESULT lres = ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
640
+ ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);
641
+ ::PostQuitMessage(0);
642
+ return lres;
643
+ }
644
+
645
+ case WM_CLOSE:
646
+ // If the user chose not to close, do *not* let the default window proc handle the message.
647
+ if (!pBA->OnClose())
648
+ {
649
+ return 0;
650
+ }
651
+ break;
652
+
653
+ case WM_WIXIUIBA_DETECT_PACKAGES: __fallthrough;
654
+ case WM_WIXIUIBA_DETECT_FOR_CLEANUP:
655
+ pBA->OnDetect();
656
+ return 0;
657
+
658
+ case WM_WIXIUIBA_PLAN_PACKAGES:
659
+ case WM_WIXIUIBA_PLAN_PACKAGES_FOR_CLEANUP:
660
+ pBA->OnPlan(static_cast<BOOTSTRAPPER_ACTION>(lParam));
661
+ return 0;
662
+
663
+ case WM_WIXIUIBA_APPLY_PACKAGES:
664
+ pBA->OnApply();
665
+ return 0;
666
+ }
667
+
668
+ return ::DefWindowProcW(hWnd, uMsg, wParam, lParam);
669
+ }
670
+
671
+
672
+ //
673
+ // OnDetect - start the processing of packages.
674
+ //
675
+ void OnDetect()
676
+ {
677
+ HRESULT hr = S_OK;
678
+
679
+ hr = m_pEngine->Detect();
680
+ BalExitOnFailure(hr, "Failed to start detecting chain.");
681
+
682
+ LExit:
683
+ if (FAILED(hr))
684
+ {
685
+ SetLoadPackageFailure(hr);
686
+ }
687
+ }
688
+
689
+
690
+ //
691
+ // OnPlan - plan the detected changes.
692
+ //
693
+ void OnPlan(
694
+ __in BOOTSTRAPPER_ACTION action
695
+ )
696
+ {
697
+ HRESULT hr = S_OK;
698
+
699
+ m_plannedAction = action;
700
+
701
+ hr = m_pEngine->Plan(action);
702
+ BalExitOnFailure(hr, "Failed to start planning packages.");
703
+
704
+ LExit:
705
+ if (FAILED(hr))
706
+ {
707
+ SetLoadPackageFailure(hr);
708
+ }
709
+ }
710
+
711
+
712
+ //
713
+ // OnApply - apply the packages.
714
+ //
715
+ void OnApply()
716
+ {
717
+ HRESULT hr = S_OK;
718
+
719
+ hr = m_pEngine->Apply(m_hWnd);
720
+ BalExitOnFailure(hr, "Failed to start applying packages.");
721
+
722
+ LExit:
723
+ if (FAILED(hr))
724
+ {
725
+ SetLoadPackageFailure(hr);
726
+ }
727
+ }
728
+
729
+
730
+ //
731
+ // OnClose - called when the window is trying to be closed.
732
+ //
733
+ BOOL OnClose()
734
+ {
735
+ BOOL fClose = FALSE;
736
+
737
+ // If we've already applied, just close.
738
+ if (m_fApplied)
739
+ {
740
+ fClose = TRUE;
741
+ }
742
+ else
743
+ {
744
+ PromptCancel(m_hWnd, TRUE, NULL, NULL);
745
+
746
+ // If we're inside Apply then we never close, we just cancel to let rollback occur.
747
+ fClose = !m_fApplying;
748
+ }
749
+
750
+ return fClose;
751
+ }
752
+
753
+
754
+ HRESULT EvaluateConditions()
755
+ {
756
+ HRESULT hr = S_OK;
757
+ BOOL fResult = FALSE;
758
+
759
+ for (DWORD i = 0; i < m_Conditions.cConditions; ++i)
760
+ {
761
+ BAL_CONDITION* pCondition = m_Conditions.rgConditions + i;
762
+
763
+ hr = BalConditionEvaluate(pCondition, m_pEngine, &fResult, &m_sczFailedMessage);
764
+ BalExitOnFailure(hr, "Failed to evaluate condition.");
765
+
766
+ if (!fResult)
767
+ {
768
+ hr = E_WIXSTDBA_CONDITION_FAILED;
769
+ BalExitOnFailure(hr, "%ls", m_sczFailedMessage);
770
+ }
771
+ }
772
+
773
+ ReleaseNullStrSecure(m_sczFailedMessage);
774
+
775
+ LExit:
776
+ return hr;
777
+ }
778
+
779
+
780
+ void SetLoadPackageFailure(
781
+ __in HRESULT hrStatus
782
+ )
783
+ {
784
+ Assert(FAILED(hrStatus));
785
+
786
+ if (!m_fApplied)
787
+ {
788
+ m_hrFinal = hrStatus;
789
+ m_fFailedToLoadPackage = TRUE;
790
+ }
791
+
792
+ // Quietly exit.
793
+ ::PostMessageW(m_hWnd, WM_CLOSE, 0, 0);
794
+ }
795
+
796
+
797
+public:
798
+ //
799
+ // Constructor - initialize member variables.
800
+ //
801
+ CWixInternalUIBootstrapperApplication(
802
+ __in HMODULE hModule,
803
+ __in_opt PREQBA_DATA* pPrereqData,
804
+ __in IBootstrapperEngine* pEngine
805
+ ) : CBalBaseBootstrapperApplication(pEngine, 3, 3000)
806
+ {
807
+ m_hModule = hModule;
808
+ m_command = { };
809
+ m_createArgs = { };
810
+
811
+ m_plannedAction = BOOTSTRAPPER_ACTION_UNKNOWN;
812
+
813
+ m_Bundle = { };
814
+ m_Conditions = { };
815
+ m_sczConfirmCloseMessage = NULL;
816
+ m_sczFailedMessage = NULL;
817
+
818
+ m_hUiThread = NULL;
819
+ m_fRegistered = FALSE;
820
+ m_hWnd = NULL;
821
+
822
+ m_hrFinal = S_OK;
823
+
824
+ m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE;
825
+
826
+ m_fApplying = FALSE;
827
+ m_fApplied = FALSE;
828
+ m_fAutomaticRemoval = FALSE;
829
+ m_fFailedToLoadPackage = FALSE;
830
+ m_pPrereqData = pPrereqData;
831
+
832
+ pEngine->AddRef();
833
+ m_pEngine = pEngine;
834
+ }
835
+
836
+
837
+ //
838
+ // Destructor - release member variables.
839
+ //
840
+ ~CWixInternalUIBootstrapperApplication()
841
+ {
842
+ ReleaseStr(m_sczFailedMessage);
843
+ ReleaseStr(m_sczConfirmCloseMessage);
844
+ BalConditionsUninitialize(&m_Conditions);
845
+ BalInfoUninitialize(&m_Bundle);
846
+
847
+ ReleaseNullObject(m_pEngine);
848
+ }
849
+
850
+private:
851
+ HMODULE m_hModule;
852
+ BOOTSTRAPPER_CREATE_ARGS m_createArgs;
853
+ BOOTSTRAPPER_COMMAND m_command;
854
+ IBootstrapperEngine* m_pEngine;
855
+ BOOTSTRAPPER_ACTION m_plannedAction;
856
+
857
+ BAL_INFO_BUNDLE m_Bundle;
858
+ BAL_CONDITIONS m_Conditions;
859
+ LPWSTR m_sczFailedMessage;
860
+ LPWSTR m_sczConfirmCloseMessage;
861
+
862
+ HANDLE m_hUiThread;
863
+ BOOL m_fRegistered;
864
+ HWND m_hWnd;
865
+
866
+ HRESULT m_hrFinal;
867
+
868
+ BOOTSTRAPPER_APPLY_RESTART m_restartResult;
869
+
870
+ BOOL m_fApplying;
871
+ BOOL m_fApplied;
872
+ BOOL m_fAutomaticRemoval;
873
+ BOOL m_fFailedToLoadPackage;
874
+ PREQBA_DATA* m_pPrereqData;
875
+};
876
+
877
+
878
+//
879
+// CreateBootstrapperApplication - creates a new IBootstrapperApplication object.
880
+//
881
+HRESULT CreateBootstrapperApplication(
882
+ __in HMODULE hModule,
883
+ __in_opt PREQBA_DATA* pPrereqData,
884
+ __in IBootstrapperEngine* pEngine,
885
+ __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
886
+ __inout BOOTSTRAPPER_CREATE_RESULTS* pResults,
887
+ __out IBootstrapperApplication** ppApplication
888
+ )
889
+{
890
+ HRESULT hr = S_OK;
891
+ CWixInternalUIBootstrapperApplication* pApplication = NULL;
892
+
893
+ pApplication = new CWixInternalUIBootstrapperApplication(hModule, pPrereqData, pEngine);
894
+ BalExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new InternalUI bootstrapper application object.");
895
+
896
+ hr = pApplication->Initialize(pArgs);
897
+ ExitOnFailure(hr, "CWixInternalUIBootstrapperApplication initialization failed.");
898
+
899
+ pResults->pfnBootstrapperApplicationProc = BalBaseBootstrapperApplicationProc;
900
+ pResults->pvBootstrapperApplicationProcContext = pApplication;
901
+ *ppApplication = pApplication;
902
+ pApplication = NULL;
903
+
904
+LExit:
905
+ ReleaseObject(pApplication);
906
+ return hr;
907
+}
908
+
909
+
910
+void DestroyBootstrapperApplication(
911
+ __in IBootstrapperApplication* pApplication,
912
+ __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
913
+ __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults
914
+ )
915
+{
916
+ CWixInternalUIBootstrapperApplication* pBA = (CWixInternalUIBootstrapperApplication*)pApplication;
917
+ pBA->Uninitialize(pArgs, pResults);
918
+}
src/ext/Bal/wixiuiba/WixInternalUIBootstrapperApplication.h
new
+18
@@ -0,0 +1,18 @@
1
+#pragma once
2
+// 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.
3
+
4
+
5
+HRESULT CreateBootstrapperApplication(
6
+ __in HMODULE hModule,
7
+ __in_opt PREQBA_DATA* pPrereqData,
8
+ __in IBootstrapperEngine* pEngine,
9
+ __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
10
+ __inout BOOTSTRAPPER_CREATE_RESULTS* pResults,
11
+ __out IBootstrapperApplication** ppApplication
12
+ );
13
+
14
+void DestroyBootstrapperApplication(
15
+ __in IBootstrapperApplication* pApplication,
16
+ __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
17
+ __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults
18
+ );
src/ext/Bal/wixiuiba/precomp.cpp
new
+3
@@ -0,0 +1,3 @@
1
+// 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.
2
+
3
+#include "precomp.h"
src/ext/Bal/wixiuiba/precomp.h
new
+30
@@ -0,0 +1,30 @@
1
+#pragma once
2
+// 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.
3
+
4
+
5
+#include <windows.h>
6
+#include <msiquery.h>
7
+
8
+#include <dutil.h>
9
+#include <dictutil.h>
10
+#include <locutil.h>
11
+#include <osutil.h>
12
+#include <pathutil.h>
13
+#include <procutil.h>
14
+#include <regutil.h>
15
+#include <strutil.h>
16
+#include <xmlutil.h>
17
+
18
+#include <BootstrapperEngine.h>
19
+#include <BootstrapperApplication.h>
20
+#include <IBootstrapperEngine.h>
21
+#include <IBootstrapperApplication.h>
22
+
23
+#include <balutil.h>
24
+#include <balinfo.h>
25
+#include <balcondition.h>
26
+
27
+#include <preqba.h>
28
+
29
+#include "WixInternalUIBootstrapperApplication.h"
30
+#include "wixiuiba.h"
src/ext/Bal/wixiuiba/wixiuiba.cpp
new
+192
@@ -0,0 +1,192 @@
1
+// 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.
2
+
3
+#include "precomp.h"
4
+
5
+static INTERNAL_UI_BA_STATE vstate = { };
6
+
7
+
8
+// internal function declarations
9
+
10
+static HRESULT LoadModulePaths(
11
+ __in INTERNAL_UI_BA_STATE* pState
12
+ );
13
+static HRESULT LoadInternalUIBAConfiguration(
14
+ __in INTERNAL_UI_BA_STATE* pState,
15
+ __in const BOOTSTRAPPER_CREATE_ARGS* pArgs
16
+ );
17
+static HRESULT CreatePrerequisiteBA(
18
+ __in INTERNAL_UI_BA_STATE* pState,
19
+ __in IBootstrapperEngine* pEngine,
20
+ __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
21
+ __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
22
+ );
23
+
24
+
25
+// function definitions
26
+
27
+extern "C" BOOL WINAPI DllMain(
28
+ __in HINSTANCE hInstance,
29
+ __in DWORD dwReason,
30
+ __in LPVOID /*pvReserved*/
31
+ )
32
+{
33
+ switch (dwReason)
34
+ {
35
+ case DLL_PROCESS_ATTACH:
36
+ ::DisableThreadLibraryCalls(hInstance);
37
+ vstate.hInstance = hInstance;
38
+ break;
39
+
40
+ case DLL_PROCESS_DETACH:
41
+ vstate.hInstance = NULL;
42
+ break;
43
+ }
44
+
45
+ return TRUE;
46
+}
47
+
48
+// Note: This function assumes that COM was already initialized on the thread.
49
+extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
50
+ __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
51
+ __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
52
+ )
53
+{
54
+ HRESULT hr = S_OK;
55
+ IBootstrapperEngine* pEngine = NULL;
56
+
57
+ hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
58
+ ExitOnFailure(hr, "Failed to initialize Bal.");
59
+
60
+ if (!vstate.fInitialized)
61
+ {
62
+ hr = XmlInitialize();
63
+ BalExitOnFailure(hr, "Failed to initialize XML.");
64
+
65
+ hr = LoadModulePaths(&vstate);
66
+ BalExitOnFailure(hr, "Failed to load the module paths.");
67
+
68
+ hr = LoadInternalUIBAConfiguration(&vstate, pArgs);
69
+ BalExitOnFailure(hr, "Failed to get the InternalUIBA configuration.");
70
+
71
+ vstate.fInitialized = TRUE;
72
+ }
73
+
74
+ if (vstate.prereqData.fAlwaysInstallPrereqs && !vstate.prereqData.fCompleted ||
75
+ FAILED(vstate.prereqData.hrFatalError))
76
+ {
77
+ BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application.");
78
+
79
+ hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults);
80
+ BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
81
+ }
82
+ else
83
+ {
84
+ hr = CreateBootstrapperApplication(vstate.hInstance, &vstate.prereqData, pEngine, pArgs, pResults, &vstate.pApplication);
85
+ BalExitOnFailure(hr, "Failed to create bootstrapper application interface.");
86
+ }
87
+
88
+LExit:
89
+ ReleaseNullObject(pEngine);
90
+
91
+ return hr;
92
+}
93
+
94
+extern "C" void WINAPI BootstrapperApplicationDestroy(
95
+ __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
96
+ __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
97
+ )
98
+{
99
+ BOOTSTRAPPER_DESTROY_RESULTS childResults = { };
100
+
101
+ if (vstate.hPrereqModule)
102
+ {
103
+ PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hPrereqModule, "PrereqBootstrapperApplicationDestroy"));
104
+ if (pfnDestroy)
105
+ {
106
+ (*pfnDestroy)(pArgs, &childResults);
107
+ }
108
+
109
+ ::FreeLibrary(vstate.hPrereqModule);
110
+ vstate.hPrereqModule = NULL;
111
+ }
112
+
113
+ if (vstate.pApplication)
114
+ {
115
+ DestroyBootstrapperApplication(vstate.pApplication, pArgs, pResults);
116
+ ReleaseNullObject(vstate.pApplication);
117
+ }
118
+
119
+ BalUninitialize();
120
+
121
+ // Need to keep track of state between reloads.
122
+ pResults->fDisableUnloading = TRUE;
123
+}
124
+
125
+static HRESULT LoadModulePaths(
126
+ __in INTERNAL_UI_BA_STATE* pState
127
+ )
128
+{
129
+ HRESULT hr = S_OK;
130
+ LPWSTR sczFullPath = NULL;
131
+
132
+ hr = PathForCurrentProcess(&sczFullPath, pState->hInstance);
133
+ ExitOnFailure(hr, "Failed to get the full host path.");
134
+
135
+ hr = PathGetDirectory(sczFullPath, &pState->sczAppBase);
136
+ ExitOnFailure(hr, "Failed to get the directory of the full process path.");
137
+
138
+LExit:
139
+ ReleaseStr(sczFullPath);
140
+
141
+ return hr;
142
+}
143
+
144
+static HRESULT LoadInternalUIBAConfiguration(
145
+ __in INTERNAL_UI_BA_STATE* pState,
146
+ __in const BOOTSTRAPPER_CREATE_ARGS* /*pArgs*/
147
+ )
148
+{
149
+ HRESULT hr = S_OK;
150
+
151
+ pState->prereqData.fAlwaysInstallPrereqs = TRUE;
152
+ pState->prereqData.fPerformHelp = TRUE;
153
+ pState->prereqData.fPerformLayout = TRUE;
154
+
155
+ return hr;
156
+}
157
+
158
+static HRESULT CreatePrerequisiteBA(
159
+ __in INTERNAL_UI_BA_STATE* pState,
160
+ __in IBootstrapperEngine* pEngine,
161
+ __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
162
+ __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
163
+ )
164
+{
165
+ HRESULT hr = S_OK;
166
+ LPWSTR sczPrereqPath = NULL;
167
+ HMODULE hModule = NULL;
168
+
169
+ hr = PathConcat(pState->sczAppBase, L"prereqba.dll", &sczPrereqPath);
170
+ BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
171
+
172
+ hModule = ::LoadLibraryExW(sczPrereqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
173
+ ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
174
+
175
+ PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate"));
176
+ ExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczPrereqPath);
177
+
178
+ hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults);
179
+ ExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
180
+
181
+ pState->hPrereqModule = hModule;
182
+ hModule = NULL;
183
+
184
+LExit:
185
+ if (hModule)
186
+ {
187
+ ::FreeLibrary(hModule);
188
+ }
189
+ ReleaseStr(sczPrereqPath);
190
+
191
+ return hr;
192
+}
src/ext/Bal/wixiuiba/wixiuiba.def
new
+6
@@ -0,0 +1,6 @@
1
+; 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.
2
+
3
+
4
+EXPORTS
5
+ BootstrapperApplicationCreate
6
+ BootstrapperApplicationDestroy
src/ext/Bal/wixiuiba/wixiuiba.h
new
+13
@@ -0,0 +1,13 @@
1
+#pragma once
2
+// 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.
3
+
4
+
5
+struct INTERNAL_UI_BA_STATE
6
+{
7
+ BOOL fInitialized;
8
+ HINSTANCE hInstance;
9
+ LPWSTR sczAppBase;
10
+ HMODULE hPrereqModule;
11
+ PREQBA_DATA prereqData;
12
+ IBootstrapperApplication* pApplication;
13
+};
src/ext/Bal/wixiuiba/wixiuiba.vcxproj
new
+72
@@ -0,0 +1,72 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- 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. -->
3
+
4
+<Project DefaultTargets="Build" Toolsxmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5
+ <ItemGroup Label="ProjectConfigurations">
6
+ <ProjectConfiguration Include="Debug|ARM64">
7
+ <Configuration>Debug</Configuration>
8
+ <Platform>ARM64</Platform>
9
+ </ProjectConfiguration>
10
+ <ProjectConfiguration Include="Release|ARM64">
11
+ <Configuration>Release</Configuration>
12
+ <Platform>ARM64</Platform>
13
+ </ProjectConfiguration>
14
+ <ProjectConfiguration Include="Debug|Win32">
15
+ <Configuration>Debug</Configuration>
16
+ <Platform>Win32</Platform>
17
+ </ProjectConfiguration>
18
+ <ProjectConfiguration Include="Release|Win32">
19
+ <Configuration>Release</Configuration>
20
+ <Platform>Win32</Platform>
21
+ </ProjectConfiguration>
22
+ <ProjectConfiguration Include="Debug|x64">
23
+ <Configuration>Debug</Configuration>
24
+ <Platform>x64</Platform>
25
+ </ProjectConfiguration>
26
+ <ProjectConfiguration Include="Release|x64">
27
+ <Configuration>Release</Configuration>
28
+ <Platform>x64</Platform>
29
+ </ProjectConfiguration>
30
+ </ItemGroup>
31
+
32
+ <PropertyGroup Label="Globals">
33
+ <ProjectGuid>{0F73E566-925C-448D-99CB-3A7F5DF399C8}</ProjectGuid>
34
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
35
+ <CharacterSet>Unicode</CharacterSet>
36
+ <TargetName>wixiuiba</TargetName>
37
+ <ProjectModuleDefinitionFile>wixiuiba.def</ProjectModuleDefinitionFile>
38
+ </PropertyGroup>
39
+
40
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
41
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
42
+
43
+ <PropertyGroup>
44
+ <ProjectAdditionalIncludeDirectories>..\wixstdba\inc</ProjectAdditionalIncludeDirectories>
45
+ <ProjectAdditionalLinkLibraries>shlwapi.lib</ProjectAdditionalLinkLibraries>
46
+ </PropertyGroup>
47
+
48
+ <ItemGroup>
49
+ <ClCompile Include="precomp.cpp">
50
+ <PrecompiledHeader>Create</PrecompiledHeader>
51
+ </ClCompile>
52
+ <ClCompile Include="WixInternalUIBootstrapperApplication.cpp" />
53
+ <ClCompile Include="wixiuiba.cpp" />
54
+ </ItemGroup>
55
+ <ItemGroup>
56
+ <ClInclude Include="precomp.h" />
57
+ <ClInclude Include="WixInternalUIBootstrapperApplication.h" />
58
+ <ClInclude Include="wixiuiba.h" />
59
+ </ItemGroup>
60
+ <ItemGroup>
61
+ <None Include="wixiuiba.def" />
62
+ </ItemGroup>
63
+
64
+ <ItemGroup>
65
+ <PackageReference Include="WixToolset.BalUtil" />
66
+
67
+ <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
68
+ <PackageReference Include="GitInfo" PrivateAssets="All" />
69
+ </ItemGroup>
70
+
71
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
72
+</Project>
src/ext/Bal/wixlib/BalExtension_platform.wxi
+14
@@ -18,6 +18,20 @@
18
<BootstrapperApplicationRef Id="WixDotNetCoreBootstrapperApplicationHost$(var.Suffix)" />
19
</Fragment>
20
21
+ <Fragment>
22
+ <BootstrapperApplication Id="WixInternalUIBootstrapperApplication$(var.Suffix)">
23
+ <BootstrapperApplicationDll Id="WixInternalUIBootstrapperApplication" SourceFile="!(bindpath.$(var.platform))\wixiuiba.dll" />
24
+ <Payload SourceFile="!(bindpath.$(var.platform))\wixstdba.dll" Name="prereqba.dll" />
25
+ </BootstrapperApplication>
26
+ </Fragment>
27
+
28
+ <Fragment>
29
+ <BootstrapperApplication Id="WixInternalUIBootstrapperApplication.Standard$(var.Suffix)">
30
+ <PayloadGroupRef Id="WixIuibaStandardPayloads" />
31
+ </BootstrapperApplication>
32
+ <BootstrapperApplicationRef Id="WixInternalUIBootstrapperApplication$(var.Suffix)" />
33
+ </Fragment>
34
+
35
<Fragment>
36
<BootstrapperApplication Id="WixStandardBootstrapperApplication$(var.Suffix)">
37
<BootstrapperApplicationDll Id="WixStandardBootstrapperApplication" SourceFile="!(bindpath.$(var.platform))\wixstdba.dll" />
src/ext/Bal/wixlib/bal.wixproj
+3
@@ -22,6 +22,9 @@
22
<ProjectReference Include="..\mbahost\mbahost.vcxproj" Properties="Platform=x86" ReferenceOutputAssembly="false" />
23
<ProjectReference Include="..\mbahost\mbahost.vcxproj" Properties="Platform=x64" ReferenceOutputAssembly="false" />
24
<ProjectReference Include="..\mbahost\mbahost.vcxproj" Properties="Platform=ARM64" ReferenceOutputAssembly="false" />
25
+ <ProjectReference Include="..\wixiuiba\wixiuiba.vcxproj" Properties="Platform=x86" ReferenceOutputAssembly="false" />
26
+ <ProjectReference Include="..\wixiuiba\wixiuiba.vcxproj" Properties="Platform=x64" ReferenceOutputAssembly="false" />
27
+ <ProjectReference Include="..\wixiuiba\wixiuiba.vcxproj" Properties="Platform=ARM64" ReferenceOutputAssembly="false" />
28
<ProjectReference Include="..\wixstdba\wixstdba.vcxproj" Properties="Platform=x86" ReferenceOutputAssembly="false" />
29
<ProjectReference Include="..\wixstdba\wixstdba.vcxproj" Properties="Platform=x64" ReferenceOutputAssembly="false" />
30
<ProjectReference Include="..\wixstdba\wixstdba.vcxproj" Properties="Platform=ARM64" ReferenceOutputAssembly="false" />
src/ext/Bal/wixlib/wixiuiba.wxs
new
+12
@@ -0,0 +1,12 @@
1
+<!-- 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. -->
2
+
3
+
4
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
5
+ <Fragment>
6
+ <PayloadGroup Id="WixIuibaStandardPayloads">
7
+ <Payload Name="mbapreq.thm" SourceFile="!(wix.WixIuibaThemeXml=SourceDir\iuipreq.thm)" />
8
+ <Payload Name="mbapreq.png" SourceFile="!(wix.WixIuibaLogo=SourceDir\mbapreq.png)" />
9
+ <Payload Name="mbapreq.wxl" SourceFile="!(wix.WixIuibaThemeWxl=SourceDir\iuipreq.wxl)" />
10
+ </PayloadGroup>
11
+ </Fragment>
12
+</Wix>
src/ext/Bal/wixstdba/Resources/iuipreq.thm
new
+67
@@ -0,0 +1,67 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Theme xmlns="http://wixtoolset.org/schemas/v4/thmutil">
3
+ <Font Id="0" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
4
+ <Font Id="1" Height="-24" Weight="500" Foreground="windowtext">Segoe UI</Font>
5
+ <Font Id="2" Height="-22" Weight="500" Foreground="graytext">Segoe UI</Font>
6
+ <Font Id="3" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
7
+
8
+ <Window Width="485" Height="300" HexStyle="100a0000" FontId="0" Caption="#(loc.Caption)">
9
+ <ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="mbapreq.png" Visible="yes"/>
10
+ <Label X="80" Y="11" Width="-11" Height="96" FontId="1" Visible="yes" DisablePrefix="yes">
11
+ <Text>#(loc.Title)</Text>
12
+ <Text Condition="WixBundleAction = 2 OR WixBundleCommandLineAction = 1">#(loc.NonPrereqTitle)</Text>
13
+ </Label>
14
+
15
+ <Page Name="Help">
16
+ <Label X="11" Y="112" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Label>
17
+ <Label X="11" Y="153" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Label>
18
+ <Button Name="HelpCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
19
+ <Text>#(loc.HelpCloseButton)</Text>
20
+ <CloseWindowAction />
21
+ </Button>
22
+ </Page>
23
+ <Page Name="Install">
24
+ <Hypertext Name="EulaHyperlink" X="11" Y="121" Width="-11" Height="34" TabStop="yes" FontId="3">#(loc.InstallLicenseTerms)</Hypertext>
25
+ <Button Name="InstallButton" X="-91" Y="-11" Width="130" Height="23" TabStop="yes" FontId="0">#(loc.InstallAcceptAndInstallButton)</Button>
26
+ <Button Name="InstallDeclineButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
27
+ <Text>#(loc.InstallDeclineButton)</Text>
28
+ <CloseWindowAction />
29
+ </Button>
30
+ </Page>
31
+ <Page Name="Progress">
32
+ <Label X="11" Y="112" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Label>
33
+ <Label X="11" Y="153" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Label>
34
+ <Label Name="OverallProgressPackageText" X="85" Y="153" Width="-11" Height="17" FontId="3" DisablePrefix="yes">[ProgressPackageName]</Label>
35
+ <Progressbar Name="OverallCalculatedProgressbar" X="11" Y="175" Width="-11" Height="15" />
36
+ <Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
37
+ </Page>
38
+ <Page Name="Success">
39
+ <Label X="11" Y="112" Width="-11" Height="30" FontId="2" DisablePrefix="yes">
40
+ <Text>#(loc.SuccessHeader)</Text>
41
+ <Text Condition="WixBundleAction = 2">#(loc.SuccessLayoutHeader)</Text>
42
+ </Label>
43
+ <Label X="-11" Y="-20" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">
44
+ <Text>#(loc.SuccessRestartText)</Text>
45
+ </Label>
46
+ <Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
47
+ <Button Name="SuccessCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
48
+ <Text>#(loc.SuccessCloseButton)</Text>
49
+ <CloseWindowAction />
50
+ </Button>
51
+ </Page>
52
+ <Page Name="Failure">
53
+ <Label X="11" Y="112" Width="-11" Height="30" FontId="2" DisablePrefix="yes">
54
+ <Text>#(loc.FailureHeader)</Text>
55
+ <Text Condition="WixBundleAction = 2">#(loc.FailureLayoutHeader)</Text>
56
+ </Label>
57
+ <Hypertext Name="FailureLogFileLink" X="11" Y="153" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureLogLinkText)</Hypertext>
58
+ <Hypertext Name="FailureMessageText" X="22" Y="190" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes"/>
59
+ <Label X="-11" Y="-20" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">#(loc.FailureRestartText)</Label>
60
+ <Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
61
+ <Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
62
+ <Text>#(loc.FailureCloseButton)</Text>
63
+ <CloseWindowAction />
64
+ </Button>
65
+ </Page>
66
+ </Window>
67
+</Theme>
src/ext/Bal/wixstdba/Resources/iuipreq.wxl
new
+34
@@ -0,0 +1,34 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<WixLocalization Culture="en-us" Language="1033" xmlns="http://wixtoolset.org/schemas/v4/wxl">
6
+ <String Id="Caption">[WixBundleName] Prerequisite Setup</String>
7
+ <String Id="Title">Prerequisite required for [WixBundleName] setup</String>
8
+ <String Id="NonPrereqTitle">[WixBundleName] setup</String>
9
+ <String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>
10
+ <String Id="HelpHeader">Setup Help</String>
11
+ <String Id="HelpText">/passive | /quiet - displays minimal UI with no prompts or displays no UI and
12
+ no prompts. By default UI and all prompts are displayed.
13
+
14
+/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String>
15
+ <String Id="HelpCloseButton">&Close</String>
16
+ <String Id="InstallLicenseTerms">Click the "Accept and Install" button to accept the prerequisite <a href="#">license terms</a>.</String>
17
+ <String Id="InstallAcceptAndInstallButton">&Accept and Install</String>
18
+ <String Id="InstallDeclineButton">&Decline</String>
19
+ <String Id="ProgressHeader">Setup Progress</String>
20
+ <String Id="ProgressLabel">Processing:</String>
21
+ <String Id="ProgressCancelButton">&Cancel</String>
22
+ <String Id="SuccessHeader">Prerequisite Setup Successful</String>
23
+ <String Id="SuccessLayoutHeader">Layout Successfully Completed</String>
24
+ <String Id="SuccessRestartText">You must restart your computer before [WixBundleName] setup can continue.</String>
25
+ <String Id="SuccessRestartButton">&Restart</String>
26
+ <String Id="SuccessCloseButton">&Close</String>
27
+ <String Id="FailureHeader">Setup Failed</String>
28
+ <String Id="FailureLayoutHeader">Layout Failed</String>
29
+ <String Id="FailureLogLinkText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>.</String>
30
+ <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
31
+ <String Id="FailureRestartButton">&Restart</String>
32
+ <String Id="FailureCloseButton">&Close</String>
33
+ <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34
+</WixLocalization>
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+27
-14
@@ -248,10 +248,20 @@ public: // IBootstrapperApplication
248
249
if (m_fPrereq)
250
{
251
- // Pre-req BA should only show help or do an install (to launch the Managed BA which can then do the right action).
252
- if (BOOTSTRAPPER_ACTION_HELP != m_command.action)
251
+ if (m_pPrereqData->fPerformLayout && BOOTSTRAPPER_ACTION_LAYOUT == m_command.action)
252
{
254
- m_command.action = BOOTSTRAPPER_ACTION_INSTALL;
253
+ // The parent BA has requested that this BA be in charge of layout.
254
+ m_fPrereq = FALSE;
255
+ }
256
+ else
257
+ {
258
+ m_fPreplanPrereqs = m_pPrereqData->fAlwaysInstallPrereqs;
259
+
260
+ // Pre-req BA should only show help or do an install (to launch the parent BA which can then do the right action).
261
+ if (BOOTSTRAPPER_ACTION_HELP != m_command.action)
262
+ {
263
+ m_command.action = BOOTSTRAPPER_ACTION_INSTALL;
264
+ }
265
}
266
}
267
else // maybe modify the action state if the bundle is or is not already installed.
@@ -527,11 +537,11 @@ public: // IBootstrapperApplication
537
)
538
{
539
HRESULT hr = S_OK;
530
- BOOL fPlannedPrereqs = WIXSTDBA_STATE_PLANNING_PREREQS == m_state;
540
+ BOOL fPreplannedPrereqs = WIXSTDBA_STATE_PLANNING_PREREQS == m_state;
541
WIXSTDBA_STATE completedState = WIXSTDBA_STATE_PLANNED;
542
BOOL fApply = TRUE;
543
534
- if (fPlannedPrereqs)
544
+ if (fPreplannedPrereqs)
545
{
546
if (SUCCEEDED(hrStatus) && !m_fPrereqPackagePlanned)
547
{
@@ -547,7 +557,7 @@ public: // IBootstrapperApplication
557
// Need to force the state change since normally moving backwards is prevented.
558
::PostMessageW(m_hWnd, WM_WIXSTDBA_CHANGE_STATE, 0, WIXSTDBA_STATE_HELP);
559
550
- ::PostMessageW(m_hWnd, WM_WIXSTDBA_SHOW_HELP, 0, 0);
560
+ ::PostMessageW(m_hWnd, WM_WIXSTDBA_SHOW_HELP, 0, 0);
561
562
ExitFunction();
563
}
@@ -562,7 +572,7 @@ public: // IBootstrapperApplication
572
ExitFunction();
573
}
574
565
- if (fPlannedPrereqs)
575
+ if (fPreplannedPrereqs)
576
{
577
// If the UI should be visible, display it now and hide the splash screen
578
if (BOOTSTRAPPER_DISPLAY_NONE < m_command.display)
@@ -1056,13 +1066,14 @@ public: // IBootstrapperApplication
1066
1067
hr = __super::OnExecutePackageComplete(wzPackageId, hrStatus, restart, recommendation, pAction);
1068
1059
- BAL_INFO_PACKAGE* pPackage = NULL;
1060
- HRESULT hrPrereq = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
1061
- if (SUCCEEDED(hrPrereq))
1069
+ if (m_fPrereq && BOOTSTRAPPER_APPLY_RESTART_NONE != restart)
1070
{
1071
+ BAL_INFO_PACKAGE* pPackage = NULL;
1072
+ HRESULT hrPrereq = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
1073
+
1074
// If the prerequisite required a restart (any restart) then do an immediate
1075
// restart to ensure that the bundle will get launched again post reboot.
1065
- if (m_fPrereq && pPackage->fPrereqPackage && BOOTSTRAPPER_APPLY_RESTART_NONE != restart)
1076
+ if (SUCCEEDED(hrPrereq) && pPackage->fPrereqPackage)
1077
{
1078
*pAction = BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_RESTART;
1079
}
@@ -2283,7 +2294,7 @@ private:
2294
// Okay, we're ready for packages now.
2295
pThis->SetState(WIXSTDBA_STATE_INITIALIZED, hr);
2296
2286
- if (!pThis->m_fPreplanPrereqs && BOOTSTRAPPER_ACTION_HELP == pThis->m_command.action)
2297
+ if (pThis->m_fPerformHelp && BOOTSTRAPPER_ACTION_HELP == pThis->m_command.action)
2298
{
2299
firstAction = WM_WIXSTDBA_SHOW_HELP;
2300
}
@@ -4246,7 +4257,7 @@ public:
4257
m_hWnd = NULL;
4258
4259
m_state = WIXSTDBA_STATE_INITIALIZING;
4249
- m_hrFinal = pPrereqData ? pPrereqData->hrHostInitialization : S_OK;
4260
+ m_hrFinal = pPrereqData ? pPrereqData->hrFatalError : S_OK;
4261
4262
m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE;
4263
m_fRestartRequired = FALSE;
@@ -4269,7 +4280,8 @@ public:
4280
4281
m_pPrereqData = pPrereqData;
4282
m_fPrereq = NULL != pPrereqData;
4272
- m_fPreplanPrereqs = m_fPrereq && m_pPrereqData->fAlwaysInstallPrereqs;
4283
+ m_fPreplanPrereqs = FALSE;
4284
+ m_fPerformHelp = !m_fPrereq || m_pPrereqData->fPerformHelp;
4285
m_fPrereqPackagePlanned = FALSE;
4286
m_fPrereqInstalled = FALSE;
4287
m_fPrereqSkipped = FALSE;
@@ -4554,6 +4566,7 @@ private:
4566
PREQBA_DATA* m_pPrereqData;
4567
BOOL m_fPrereq;
4568
BOOL m_fPreplanPrereqs;
4569
+ BOOL m_fPerformHelp;
4570
BOOL m_fPrereqPackagePlanned;
4571
BOOL m_fPrereqInstalled;
4572
BOOL m_fPrereqSkipped;
src/ext/Bal/wixstdba/inc/preqba.h
+3
-1
@@ -4,8 +4,10 @@
4
5
struct PREQBA_DATA
6
{
7
- HRESULT hrHostInitialization;
7
+ HRESULT hrFatalError;
8
BOOL fAlwaysInstallPrereqs;
9
+ BOOL fPerformHelp;
10
+ BOOL fPerformLayout;
11
BOOL fCompleted;
12
};
13
src/test/burn/TestData/Templates/Bundle.wxs
+4
@@ -33,6 +33,10 @@
33
<BootstrapperApplication>
34
<bal:WixStandardBootstrapperApplication LicenseUrl="" Theme="hyperlinkLicense" />
35
</BootstrapperApplication>
36
+ <?elseif $(var.BA) = "iui"?>
37
+ <BootstrapperApplication>
38
+ <bal:WixInternalUIBootstrapperApplication />
39
+ </BootstrapperApplication>
40
<?else?>
41
<BootstrapperApplicationRef Id="$(var.BA)" />
42
<?endif?>
src/test/burn/TestData/TestData.proj
+1
-1
@@ -4,7 +4,7 @@
4
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5
<ItemGroup>
6
<TestDataProject Include="**\*.wixproj" />
7
-
7
+
8
<!-- https://github.com/wixtoolset/issues/issues/6401 -->
9
<TestDataProject Remove="DependencyTests\BundleC\BundleC.wixproj" />
10
<TestDataProject Remove="DependencyTests\BundleF_PatchAv1_0_1\BundleF_PatchAv1_0_1.wixproj" />
src/test/burn/TestData/WixIuiBaTests/ArchSpecificBundle/ArchSpecificBundle.wixproj
new
+17
@@ -0,0 +1,17 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <OutputType>Bundle</OutputType>
5
+ <BA>iui</BA>
6
+ <UpgradeCode>{22B5ADAF-74D3-424A-8D32-9901FCF97E6D}</UpgradeCode>
7
+ </PropertyGroup>
8
+ <ItemGroup>
9
+ <ProjectReference Include="..\InternalUIPackage\InternalUIPackage.wixproj" />
10
+ <ProjectReference Include="..\InternalUIarm64Package\InternalUIarm64Package.wixproj" />
11
+ <ProjectReference Include="..\InternalUIx64Package\InternalUIx64Package.wixproj" />
12
+ <ProjectReference Include="..\InternalUIx86Package\InternalUIx86Package.wixproj" />
13
+ </ItemGroup>
14
+ <ItemGroup>
15
+ <PackageReference Include="WixToolset.Bal.wixext" />
16
+ </ItemGroup>
17
+</Project>
\ No newline at end of file
src/test/burn/TestData/WixIuiBaTests/ArchSpecificBundle/ArchSpecificBundle.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<!-- 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. -->
2
+
3
+
4
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
5
+ <Fragment>
6
+ <PackageGroup Id="BundlePackages">
7
+ <MsiPackage Id="InternalUIPackage" SourceFile="$(var.InternalUIPackage.TargetPath)" />
8
+ <MsiPackage Id="InternalUIarm64Package" SourceFile="$(var.InternalUIarm64Package.TargetPath)" bal:PrimaryPackageType="arm64" />
9
+ <MsiPackage Id="InternalUIx64Package" SourceFile="$(var.InternalUIx64Package.TargetPath)" bal:PrimaryPackageType="x64" />
10
+ <MsiPackage Id="InternalUIx86Package" SourceFile="$(var.InternalUIx86Package.TargetPath)" bal:PrimaryPackageType="x86" />
11
+ </PackageGroup>
12
+ </Fragment>
13
+</Wix>
src/test/burn/TestData/WixIuiBaTests/ArchSpecificBundle/Bundle.wxs
new
+63
@@ -0,0 +1,63 @@
1
+<!-- 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. -->
2
+
3
+<?ifndef Version?>
4
+<?define Version = 1.0.0.0?>
5
+<?endif?>
6
+<?ifndef BundleLogDirectory?>
7
+<?define BundleLogDirectory = .?>
8
+<?endif?>
9
+
10
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
11
+ <!-- The only difference from the template should be the SplashScreen and uncompressed -->
12
+ <Bundle Name="~$(var.TestGroupName) - $(var.BundleName)" Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)" Compressed="no" SplashScreenSourceFile="..\..\Manual\BafThmutilTesting\theme\star_transparent.bmp">
13
+ <Log Prefix="$(var.BundleLogDirectory)\~$(var.TestGroupName)_$(var.BundleName)" />
14
+
15
+ <Variable Name="TestGroupName" Value="$(var.TestGroupName)" />
16
+
17
+ <?ifdef SoftwareTag?>
18
+ <SoftwareTag Regid="regid.1995-08.com.example" InstallPath="[CommonAppDataFolder]regid.1995-08.com.example" />
19
+ <?endif?>
20
+
21
+ <?ifndef BA?>
22
+ <!-- pulled in through the PackageGroupRef below -->
23
+ <?elseif $(var.BA) = "TestBAdnc"?>
24
+ <!-- pulled in through the PackageGroupRef below -->
25
+ <?elseif $(var.BA) = "TestBA_x64"?>
26
+ <!-- pulled in through the PackageGroupRef below -->
27
+ <?elseif $(var.BA) = "TestBAdnc_x64"?>
28
+ <!-- pulled in through the PackageGroupRef below -->
29
+ <?elseif $(var.BA) = "WixBA"?>
30
+ <!-- pulled in through the PackageGroupRef below -->
31
+ <?elseif $(var.BA) = "WixBAdnc_x64"?>
32
+ <!-- pulled in through the PackageGroupRef below -->
33
+ <?elseif $(var.BA) = "hyperlinkLicense"?>
34
+ <BootstrapperApplication>
35
+ <bal:WixStandardBootstrapperApplication LicenseUrl="" Theme="hyperlinkLicense" />
36
+ </BootstrapperApplication>
37
+ <?elseif $(var.BA) = "iui"?>
38
+ <BootstrapperApplication>
39
+ <bal:WixInternalUIBootstrapperApplication />
40
+ </BootstrapperApplication>
41
+ <?else?>
42
+ <BootstrapperApplicationRef Id="$(var.BA)" />
43
+ <?endif?>
44
+
45
+ <Chain>
46
+ <?ifndef BA?>
47
+ <PackageGroupRef Id="TestBA" />
48
+ <?elseif $(var.BA) = "TestBAdnc"?>
49
+ <PackageGroupRef Id="TestBAdnc" />
50
+ <?elseif $(var.BA) = "TestBA_x64"?>
51
+ <PackageGroupRef Id="TestBA_x64" />
52
+ <?elseif $(var.BA) = "TestBAdnc_x64"?>
53
+ <PackageGroupRef Id="TestBAdnc_x64" />
54
+ <?elseif $(var.BA) = "WixBA"?>
55
+ <PackageGroupRef Id="WixBA" />
56
+ <?elseif $(var.BA) = "WixBAdnc_x64"?>
57
+ <PackageGroupRef Id="WixBAdnc_x64" />
58
+ <?endif?>
59
+
60
+ <PackageGroupRef Id="BundlePackages" />
61
+ </Chain>
62
+ </Bundle>
63
+</Wix>
src/test/burn/TestData/WixIuiBaTests/DtfSamples.sln
renamed
+1
-1
@@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.30114.105
5
MinimumVisualStudioVersion = 10.0.40219.1
6
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmbeddedUI", "EmbeddedUI\EmbeddedUI.csproj", "{864B8C50-7895-4485-AC89-900D86FD8C0D}"
7
EndProject
8
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleCA", "SampleCA\SampleCA.csproj", "{8F53B9CC-6FBE-493D-9C9A-09B2AD578CE7}"
8
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedCA", "ManagedCA\ManagedCA.csproj", "{8F53B9CC-6FBE-493D-9C9A-09B2AD578CE7}"
9
EndProject
10
Global
11
GlobalSection(SolutionConfigurationPlatforms) = preSolution
src/test/burn/TestData/WixIuiBaTests/EmbeddedUI/EmbeddedUI.config
renamed
src/test/burn/TestData/WixIuiBaTests/EmbeddedUI/EmbeddedUI.csproj
renamed
src/test/burn/TestData/WixIuiBaTests/EmbeddedUI/InstallProgressCounter.cs
renamed
src/test/burn/TestData/WixIuiBaTests/EmbeddedUI/SampleEmbeddedUI.cs
renamed
src/test/burn/TestData/WixIuiBaTests/EmbeddedUI/SetupWizard.xaml
renamed
src/test/burn/TestData/WixIuiBaTests/EmbeddedUI/SetupWizard.xaml.cs
renamed
src/test/burn/TestData/WixIuiBaTests/EmbeddedUIBundle/Bundle.wxs
new
+63
@@ -0,0 +1,63 @@
1
+<!-- 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. -->
2
+
3
+<?ifndef Version?>
4
+<?define Version = 1.0.0.0?>
5
+<?endif?>
6
+<?ifndef BundleLogDirectory?>
7
+<?define BundleLogDirectory = .?>
8
+<?endif?>
9
+
10
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
11
+ <!-- The only difference from the template should be the SplashScreen and uncompressed -->
12
+ <Bundle Name="~$(var.TestGroupName) - $(var.BundleName)" Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)" Compressed="no" SplashScreenSourceFile="..\..\Manual\BafThmutilTesting\theme\star_transparent.bmp">
13
+ <Log Prefix="$(var.BundleLogDirectory)\~$(var.TestGroupName)_$(var.BundleName)" />
14
+
15
+ <Variable Name="TestGroupName" Value="$(var.TestGroupName)" />
16
+
17
+ <?ifdef SoftwareTag?>
18
+ <SoftwareTag Regid="regid.1995-08.com.example" InstallPath="[CommonAppDataFolder]regid.1995-08.com.example" />
19
+ <?endif?>
20
+
21
+ <?ifndef BA?>
22
+ <!-- pulled in through the PackageGroupRef below -->
23
+ <?elseif $(var.BA) = "TestBAdnc"?>
24
+ <!-- pulled in through the PackageGroupRef below -->
25
+ <?elseif $(var.BA) = "TestBA_x64"?>
26
+ <!-- pulled in through the PackageGroupRef below -->
27
+ <?elseif $(var.BA) = "TestBAdnc_x64"?>
28
+ <!-- pulled in through the PackageGroupRef below -->
29
+ <?elseif $(var.BA) = "WixBA"?>
30
+ <!-- pulled in through the PackageGroupRef below -->
31
+ <?elseif $(var.BA) = "WixBAdnc_x64"?>
32
+ <!-- pulled in through the PackageGroupRef below -->
33
+ <?elseif $(var.BA) = "hyperlinkLicense"?>
34
+ <BootstrapperApplication>
35
+ <bal:WixStandardBootstrapperApplication LicenseUrl="" Theme="hyperlinkLicense" />
36
+ </BootstrapperApplication>
37
+ <?elseif $(var.BA) = "iui"?>
38
+ <BootstrapperApplication>
39
+ <bal:WixInternalUIBootstrapperApplication />
40
+ </BootstrapperApplication>
41
+ <?else?>
42
+ <BootstrapperApplicationRef Id="$(var.BA)" />
43
+ <?endif?>
44
+
45
+ <Chain>
46
+ <?ifndef BA?>
47
+ <PackageGroupRef Id="TestBA" />
48
+ <?elseif $(var.BA) = "TestBAdnc"?>
49
+ <PackageGroupRef Id="TestBAdnc" />
50
+ <?elseif $(var.BA) = "TestBA_x64"?>
51
+ <PackageGroupRef Id="TestBA_x64" />
52
+ <?elseif $(var.BA) = "TestBAdnc_x64"?>
53
+ <PackageGroupRef Id="TestBAdnc_x64" />
54
+ <?elseif $(var.BA) = "WixBA"?>
55
+ <PackageGroupRef Id="WixBA" />
56
+ <?elseif $(var.BA) = "WixBAdnc_x64"?>
57
+ <PackageGroupRef Id="WixBAdnc_x64" />
58
+ <?endif?>
59
+
60
+ <PackageGroupRef Id="BundlePackages" />
61
+ </Chain>
62
+ </Bundle>
63
+</Wix>
src/test/burn/TestData/WixIuiBaTests/EmbeddedUIBundle/EmbeddedUIBundle.wixproj
new
+15
@@ -0,0 +1,15 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <OutputType>Bundle</OutputType>
5
+ <BA>iui</BA>
6
+ <UpgradeCode>{5115D6AC-A1FE-40C6-BEB3-BEBB39E61579}</UpgradeCode>
7
+ </PropertyGroup>
8
+ <ItemGroup>
9
+ <ProjectReference Include="..\EmbeddedUIPackage\EmbeddedUIPackage.wixproj" />
10
+ <ProjectReference Include="..\InternalUIPackage\InternalUIPackage.wixproj" />
11
+ </ItemGroup>
12
+ <ItemGroup>
13
+ <PackageReference Include="WixToolset.Bal.wixext" />
14
+ </ItemGroup>
15
+</Project>
\ No newline at end of file
src/test/burn/TestData/WixIuiBaTests/EmbeddedUIBundle/EmbeddedUIBundle.wxs
new
+11
@@ -0,0 +1,11 @@
1
+<!-- 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. -->
2
+
3
+
4
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
5
+ <Fragment>
6
+ <PackageGroup Id="BundlePackages">
7
+ <MsiPackage Id="InternalUIPackage" SourceFile="$(var.InternalUIPackage.TargetPath)" Permanent="yes" />
8
+ <MsiPackage Id="EmbeddedUIPackage" SourceFile="$(var.EmbeddedUIPackage.TargetPath)" />
9
+ </PackageGroup>
10
+ </Fragment>
11
+</Wix>
src/test/burn/TestData/WixIuiBaTests/EmbeddedUIPackage/EmbeddedUIPackage.wixproj
new
+16
@@ -0,0 +1,16 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <ProductComponentsRef>true</ProductComponentsRef>
5
+ <UpgradeCode>{A6826B6D-2F3F-456D-BABF-1B8CDCE3AE68}</UpgradeCode>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
9
+ </ItemGroup>
10
+ <ItemGroup>
11
+ <ProjectReference Include="..\EmbeddedUI\EmbeddedUI.csproj" />
12
+ </ItemGroup>
13
+ <ItemGroup>
14
+ <PackageReference Include="WixToolset.UI.wixext" />
15
+ </ItemGroup>
16
+</Project>
\ No newline at end of file
src/test/burn/TestData/WixIuiBaTests/EmbeddedUIPackage/EmbeddedUIPackage.wxs
new
+13
@@ -0,0 +1,13 @@
1
+<!-- 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. -->
2
+
3
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
4
+ <Fragment>
5
+ <ComponentGroup Id="ProductComponents" />
6
+
7
+ <ui:WixUI Id="WixUI_Minimal" />
8
+
9
+ <UI>
10
+ <EmbeddedUI SourceFile="$(var.EmbeddedUI.TargetDir)$(var.EmbeddedUI.TargetName).CA.dll" />
11
+ </UI>
12
+ </Fragment>
13
+</Wix>
src/test/burn/TestData/WixIuiBaTests/InternalUIBundle/Bundle.wxs
new
+63
@@ -0,0 +1,63 @@
1
+<!-- 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. -->
2
+
3
+<?ifndef Version?>
4
+<?define Version = 1.0.0.0?>
5
+<?endif?>
6
+<?ifndef BundleLogDirectory?>
7
+<?define BundleLogDirectory = .?>
8
+<?endif?>
9
+
10
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
11
+ <!-- The only difference from the template should be the SplashScreen and uncompressed -->
12
+ <Bundle Name="~$(var.TestGroupName) - $(var.BundleName)" Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)" Compressed="no" SplashScreenSourceFile="..\..\Manual\BafThmutilTesting\theme\star_transparent.bmp">
13
+ <Log Prefix="$(var.BundleLogDirectory)\~$(var.TestGroupName)_$(var.BundleName)" />
14
+
15
+ <Variable Name="TestGroupName" Value="$(var.TestGroupName)" />
16
+
17
+ <?ifdef SoftwareTag?>
18
+ <SoftwareTag Regid="regid.1995-08.com.example" InstallPath="[CommonAppDataFolder]regid.1995-08.com.example" />
19
+ <?endif?>
20
+
21
+ <?ifndef BA?>
22
+ <!-- pulled in through the PackageGroupRef below -->
23
+ <?elseif $(var.BA) = "TestBAdnc"?>
24
+ <!-- pulled in through the PackageGroupRef below -->
25
+ <?elseif $(var.BA) = "TestBA_x64"?>
26
+ <!-- pulled in through the PackageGroupRef below -->
27
+ <?elseif $(var.BA) = "TestBAdnc_x64"?>
28
+ <!-- pulled in through the PackageGroupRef below -->
29
+ <?elseif $(var.BA) = "WixBA"?>
30
+ <!-- pulled in through the PackageGroupRef below -->
31
+ <?elseif $(var.BA) = "WixBAdnc_x64"?>
32
+ <!-- pulled in through the PackageGroupRef below -->
33
+ <?elseif $(var.BA) = "hyperlinkLicense"?>
34
+ <BootstrapperApplication>
35
+ <bal:WixStandardBootstrapperApplication LicenseUrl="" Theme="hyperlinkLicense" />
36
+ </BootstrapperApplication>
37
+ <?elseif $(var.BA) = "iui"?>
38
+ <BootstrapperApplication>
39
+ <bal:WixInternalUIBootstrapperApplication />
40
+ </BootstrapperApplication>
41
+ <?else?>
42
+ <BootstrapperApplicationRef Id="$(var.BA)" />
43
+ <?endif?>
44
+
45
+ <Chain>
46
+ <?ifndef BA?>
47
+ <PackageGroupRef Id="TestBA" />
48
+ <?elseif $(var.BA) = "TestBAdnc"?>
49
+ <PackageGroupRef Id="TestBAdnc" />
50
+ <?elseif $(var.BA) = "TestBA_x64"?>
51
+ <PackageGroupRef Id="TestBA_x64" />
52
+ <?elseif $(var.BA) = "TestBAdnc_x64"?>
53
+ <PackageGroupRef Id="TestBAdnc_x64" />
54
+ <?elseif $(var.BA) = "WixBA"?>
55
+ <PackageGroupRef Id="WixBA" />
56
+ <?elseif $(var.BA) = "WixBAdnc_x64"?>
57
+ <PackageGroupRef Id="WixBAdnc_x64" />
58
+ <?endif?>
59
+
60
+ <PackageGroupRef Id="BundlePackages" />
61
+ </Chain>
62
+ </Bundle>
63
+</Wix>
src/test/burn/TestData/WixIuiBaTests/InternalUIBundle/InternalUIBundle.wixproj
new
+14
@@ -0,0 +1,14 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <OutputType>Bundle</OutputType>
5
+ <BA>iui</BA>
6
+ <UpgradeCode>{62CB2BAE-129D-41D1-928B-5353FC542130}</UpgradeCode>
7
+ </PropertyGroup>
8
+ <ItemGroup>
9
+ <ProjectReference Include="..\InternalUIPackage\InternalUIPackage.wixproj" />
10
+ </ItemGroup>
11
+ <ItemGroup>
12
+ <PackageReference Include="WixToolset.Bal.wixext" />
13
+ </ItemGroup>
14
+</Project>
\ No newline at end of file
src/test/burn/TestData/WixIuiBaTests/InternalUIBundle/InternalUIBundle.wxs
new
+10
@@ -0,0 +1,10 @@
1
+<!-- 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. -->
2
+
3
+
4
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
5
+ <Fragment>
6
+ <PackageGroup Id="BundlePackages">
7
+ <MsiPackage Id="InternalUIPackage" SourceFile="$(var.InternalUIPackage.TargetPath)" />
8
+ </PackageGroup>
9
+ </Fragment>
10
+</Wix>
src/test/burn/TestData/WixIuiBaTests/InternalUIPackage/InternalUIPackage.wixproj
new
+16
@@ -0,0 +1,16 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <ProductComponentsRef>true</ProductComponentsRef>
5
+ <UpgradeCode>{7A0FE267-9EAE-4780-B41E-60C9E7044F53}</UpgradeCode>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
9
+ </ItemGroup>
10
+ <ItemGroup>
11
+ <ProjectReference Include="..\ManagedCA\ManagedCA.csproj" />
12
+ </ItemGroup>
13
+ <ItemGroup>
14
+ <PackageReference Include="WixToolset.UI.wixext" />
15
+ </ItemGroup>
16
+</Project>
\ No newline at end of file
src/test/burn/TestData/WixIuiBaTests/InternalUIPackage/InternalUIPackage.wxs
new
+24
@@ -0,0 +1,24 @@
1
+<!-- 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. -->
2
+
3
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
4
+ <Fragment>
5
+ <ComponentGroup Id="ProductComponents" />
6
+
7
+ <ui:WixUI Id="WixUI_Minimal" />
8
+
9
+ <Binary Id="TestData" SourceFile="$(var.ManagedCA.TargetDir)testsub\testfile.txt" />
10
+ <Binary Id="ManagedCA" SourceFile="$(var.ManagedCA.TargetDir)$(var.ManagedCA.TargetName).CA.dll" />
11
+ <CustomAction Id="SampleCA1" BinaryRef="ManagedCA" DllEntry="SampleCA1" Execute="firstSequence" />
12
+ <CustomAction Id="SampleCustomAction2" BinaryRef="ManagedCA" DllEntry="SampleCA2" Execute="firstSequence" Return="ignore" />
13
+
14
+ <InstallUISequence>
15
+ <Custom Action="SampleCA1" After="CostFinalize" Condition="NOT Installed" />
16
+ <Custom Action="SampleCustomAction2" After="SampleCA1" Condition="NOT Installed" />
17
+ </InstallUISequence>
18
+
19
+ <InstallExecuteSequence>
20
+ <Custom Action="SampleCA1" After="CostFinalize" Condition="NOT Installed" />
21
+ <Custom Action="SampleCustomAction2" After="SampleCA1" Condition="NOT Installed" />
22
+ </InstallExecuteSequence>
23
+ </Fragment>
24
+</Wix>
src/test/burn/TestData/WixIuiBaTests/InternalUIarm64Package/InternalUIarm64Package.wixproj
new
+14
@@ -0,0 +1,14 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <InstallerPlatform>arm64</InstallerPlatform>
5
+ <ProductComponentsRef>true</ProductComponentsRef>
6
+ <UpgradeCode>{357EBF93-039C-4378-8BCB-8B53F9B9F69A}</UpgradeCode>
7
+ </PropertyGroup>
8
+ <ItemGroup>
9
+ <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
10
+ </ItemGroup>
11
+ <ItemGroup>
12
+ <PackageReference Include="WixToolset.UI.wixext" />
13
+ </ItemGroup>
14
+</Project>
\ No newline at end of file
src/test/burn/TestData/WixIuiBaTests/InternalUIarm64Package/InternalUIarm64Package.wxs
new
+9
@@ -0,0 +1,9 @@
1
+<!-- 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. -->
2
+
3
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
4
+ <Fragment>
5
+ <ComponentGroup Id="ProductComponents" />
6
+
7
+ <ui:WixUI Id="WixUI_Minimal" />
8
+ </Fragment>
9
+</Wix>
src/test/burn/TestData/WixIuiBaTests/InternalUIx64Package/InternalUIx64Package.wixproj
new
+14
@@ -0,0 +1,14 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <InstallerPlatform>x64</InstallerPlatform>
5
+ <ProductComponentsRef>true</ProductComponentsRef>
6
+ <UpgradeCode>{2EBACF8F-BECD-401C-94F2-CFA2C9C3C07F}</UpgradeCode>
7
+ </PropertyGroup>
8
+ <ItemGroup>
9
+ <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
10
+ </ItemGroup>
11
+ <ItemGroup>
12
+ <PackageReference Include="WixToolset.UI.wixext" />
13
+ </ItemGroup>
14
+</Project>
\ No newline at end of file
src/test/burn/TestData/WixIuiBaTests/InternalUIx64Package/InternalUIx64Package.wxs
new
+9
@@ -0,0 +1,9 @@
1
+<!-- 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. -->
2
+
3
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
4
+ <Fragment>
5
+ <ComponentGroup Id="ProductComponents" />
6
+
7
+ <ui:WixUI Id="WixUI_Minimal" />
8
+ </Fragment>
9
+</Wix>
src/test/burn/TestData/WixIuiBaTests/InternalUIx86Package/InternalUIx86Package.wixproj
new
+14
@@ -0,0 +1,14 @@
1
+<!-- 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. -->
2
+<Project Sdk="WixToolset.Sdk">
3
+ <PropertyGroup>
4
+ <InstallerPlatform>x64</InstallerPlatform>
5
+ <ProductComponentsRef>true</ProductComponentsRef>
6
+ <UpgradeCode>{1FA46DA0-5F83-459A-8A30-3E5A54D20A4D}</UpgradeCode>
7
+ </PropertyGroup>
8
+ <ItemGroup>
9
+ <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
10
+ </ItemGroup>
11
+ <ItemGroup>
12
+ <PackageReference Include="WixToolset.UI.wixext" />
13
+ </ItemGroup>
14
+</Project>
\ No newline at end of file
src/test/burn/TestData/WixIuiBaTests/InternalUIx86Package/InternalUIx86Package.wxs
new
+9
@@ -0,0 +1,9 @@
1
+<!-- 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. -->
2
+
3
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
4
+ <Fragment>
5
+ <ComponentGroup Id="ProductComponents" />
6
+
7
+ <ui:WixUI Id="WixUI_Minimal" />
8
+ </Fragment>
9
+</Wix>
src/test/burn/TestData/WixIuiBaTests/ManagedCA/CustomAction.config
renamed
src/test/burn/TestData/WixIuiBaTests/ManagedCA/ManagedCA.csproj
renamed
src/test/burn/TestData/WixIuiBaTests/ManagedCA/SampleCA.cs
renamed
src/test/burn/TestData/WixIuiBaTests/ManagedCA/testsub/testfile.txt
renamed
src/test/burn/WixTestTools/PackageVerifier.cs
+14
-4
@@ -63,17 +63,27 @@ namespace WixTestTools
63
return row.Value;
64
}
65
66
- public void VerifyInstalled(bool installed)
66
+ public bool IsInstalled()
67
{
68
var productCode = this.GetProperty("ProductCode");
69
- Assert.Equal(installed, MsiUtilities.IsProductInstalled(productCode));
69
+ return MsiUtilities.IsProductInstalled(productCode);
70
}
71
72
- public void VerifyInstalledWithVersion(bool installed)
72
+ public bool IsInstalledWithVersion()
73
{
74
var productCode = this.GetProperty("ProductCode");
75
Version prodVersion = new Version(this.GetProperty("ProductVersion"));
76
- Assert.Equal(installed, MsiUtilities.IsProductInstalledWithVersion(productCode, prodVersion));
76
+ return MsiUtilities.IsProductInstalledWithVersion(productCode, prodVersion);
77
+ }
78
+
79
+ public void VerifyInstalled(bool installed)
80
+ {
81
+ Assert.Equal(installed, this.IsInstalled());
82
+ }
83
+
84
+ public void VerifyInstalledWithVersion(bool installed)
85
+ {
86
+ Assert.Equal(installed, this.IsInstalledWithVersion());
87
}
88
89
public void DeleteTestRegistryValue(string name)
src/test/burn/WixToolsetTest.BurnE2E/WixIuiBaTests.cs
new
+144
@@ -0,0 +1,144 @@
1
+// 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.
2
+
3
+namespace WixToolsetTest.BurnE2E
4
+{
5
+ using WixTestTools;
6
+ using Xunit;
7
+ using Xunit.Abstractions;
8
+
9
+ public class WixIuiBaTests : BurnE2ETests
10
+ {
11
+ public WixIuiBaTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
12
+
13
+ [RuntimeFact]
14
+ public void CanInstallArchitectureSpecificPrimaryPackage()
15
+ {
16
+ var defaultPackage = this.CreatePackageInstaller("InternalUIPackage");
17
+ var x86Package = this.CreatePackageInstaller("InternalUIx86Package");
18
+ var x64Package = this.CreatePackageInstaller("InternalUIx64Package");
19
+ var arm64Package = this.CreatePackageInstaller("InternalUIarm64Package");
20
+ var bundle = this.CreateBundleInstaller("ArchSpecificBundle");
21
+
22
+ defaultPackage.VerifyInstalled(false);
23
+ x86Package.VerifyInstalled(false);
24
+ x64Package.VerifyInstalled(false);
25
+ arm64Package.VerifyInstalled(false);
26
+ bundle.VerifyUnregisteredAndRemovedFromPackageCache();
27
+
28
+ bundle.Install();
29
+ bundle.VerifyRegisteredAndInPackageCache();
30
+ defaultPackage.VerifyInstalled(false);
31
+
32
+ var archSpecificInstalls = 0;
33
+ if (x86Package.IsInstalled())
34
+ {
35
+ ++archSpecificInstalls;
36
+ }
37
+
38
+ if (x64Package.IsInstalled())
39
+ {
40
+ ++archSpecificInstalls;
41
+ }
42
+
43
+ if (arm64Package.IsInstalled())
44
+ {
45
+ ++archSpecificInstalls;
46
+ }
47
+
48
+ Assert.Equal(1, archSpecificInstalls);
49
+
50
+ bundle.Uninstall();
51
+ bundle.VerifyUnregisteredAndRemovedFromPackageCache();
52
+ defaultPackage.VerifyInstalled(false);
53
+ x86Package.VerifyInstalled(false);
54
+ x64Package.VerifyInstalled(false);
55
+ arm64Package.VerifyInstalled(false);
56
+ }
57
+
58
+ [RuntimeFact]
59
+ public void CanSilentlyInstallAndUninstallEmbeddedUIBundle()
60
+ {
61
+ var prereqPackage = this.CreatePackageInstaller("InternalUIPackage");
62
+ var package = this.CreatePackageInstaller("EmbeddedUIPackage");
63
+ var bundle = this.CreateBundleInstaller("EmbeddedUIBundle");
64
+
65
+ prereqPackage.VerifyInstalled(false);
66
+ package.VerifyInstalled(false);
67
+ bundle.VerifyUnregisteredAndRemovedFromPackageCache();
68
+
69
+ bundle.Install();
70
+ bundle.VerifyRegisteredAndInPackageCache();
71
+ prereqPackage.VerifyInstalled(true);
72
+ package.VerifyInstalled(true);
73
+
74
+ bundle.Uninstall();
75
+ bundle.VerifyUnregisteredAndRemovedFromPackageCache();
76
+ prereqPackage.VerifyInstalled(true);
77
+ package.VerifyInstalled(false);
78
+ }
79
+
80
+ [RuntimeFact]
81
+ public void CanSilentlyInstallAndUninstallInternalUIBundle()
82
+ {
83
+ var package = this.CreatePackageInstaller("InternalUIPackage");
84
+ var bundle = this.CreateBundleInstaller("InternalUIBundle");
85
+
86
+ package.VerifyInstalled(false);
87
+ bundle.VerifyUnregisteredAndRemovedFromPackageCache();
88
+
89
+ bundle.Install();
90
+ bundle.VerifyRegisteredAndInPackageCache();
91
+ package.VerifyInstalled(true);
92
+
93
+ bundle.Uninstall();
94
+ bundle.VerifyUnregisteredAndRemovedFromPackageCache();
95
+ package.VerifyInstalled(false);
96
+ }
97
+
98
+ // Manual test for EmbeddedUIBundle:
99
+ // 1. Double click EmbeddedUIBundle.exe.
100
+ // 2. Verify that the prereq BA came up and click the install button (allow elevation).
101
+ // 3. Verify that the prereq BA automatically closed after installing the prereq.
102
+ // 4. Verify that the MSI UI came up and click the install button.
103
+ // 5. After it's finished, click the exit button.
104
+ // 6. Verify that no other UI is shown and that everything was installed.
105
+ // 7. Double click EmbeddedUIBundle.exe (allow elevation).
106
+ // 8. Verify that the prereq BA did not come up.
107
+ // 9. Verify that the MSI UI came up and click the uninstall button.
108
+ // 10. After it's finished, click the exit button.
109
+ // 11. Verify that no other UI is shown and that everything was uninstalled except for the prereq which was permanent.
110
+ // 12. Uninstall InternalUIPackage to make sure the machine is clean for other tests.
111
+
112
+ // Alternate EmbeddedUIBundle test - manually install InternalUIPackage first and verify that the prereq BA doesn't come up during install either.
113
+
114
+ // Manual test for InternalUIBundle:
115
+ // 1. Double click InternalUIBundle.exe on a machine that will prompt for elevation.
116
+ // 2. Verify that the splash screen appeared but the prereq BA did not come up.
117
+ // 3. Verify that the elevation prompt came up immediately instead of flashing on the taskbar. (This is currently broken)
118
+ // 4. Allow elevation.
119
+ // 5. Verify that the MSI UI came up and the splash screen disappeared.
120
+ // 6. Accept the two CA messages and click the install button.
121
+ // 7. After it's finished, click the exit button.
122
+ // 8. Verify that no other UI is shown and that everything was installed.
123
+ // 9. Double click InternalUIBundle.exe (allow elevation).
124
+ // 10. Verify that the prereq BA did not come up.
125
+ // 11. Verify that the MSI UI came up and click the uninstall button.
126
+ // 12. After it's finished, click the exit button.
127
+ // 13. Verify that no other UI is shown and that everything was uninstalled to make sure the machine is clean for other tests.
128
+
129
+ // Manual test for Help:
130
+ // 1. Run EmbeddedUIBundle.exe /help from the command line.
131
+ // 2. Verify that the prereq BA shows the help information without trying to install the prereqs.
132
+
133
+ // Manual test for Layout:
134
+ // 1. Run EmbeddedUIBundle.exe /layout from an unelevated command line on a machine that will prompt for elevation.
135
+ // 2. Verify that the prereq BA performs the layout without requiring any input from the user.
136
+ // 3. Verify that it never prompted for elevation.
137
+ // 4. Click the exit button.
138
+
139
+ // Manual test for Caching error:
140
+ // 1. Copy InternalUIBundle.exe to a separate folder so that it can't find InternalUIPackage.msi.
141
+ // 2. Attempt to install InternalUIBundle.exe (allow elevation).
142
+ // 3. Verify that the prereq BA comes up with the Failure page saying that a file couldn't be found.
143
+ }
144
+}
src/test/dtf/Directory.Build.props
deleted
-11
@@ -1,11 +0,0 @@
1
-<?xml version="1.0" encoding="utf-8"?>
2
-<!-- 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. -->
3
-<Project>
4
- <PropertyGroup>
5
- <SegmentName>IntegrationDtf</SegmentName>
6
- <SignOutput>false</SignOutput>
7
- </PropertyGroup>
8
-
9
- <Import Project="..\..\Directory.Build.props" />
10
- <Import Project="Directory$(MSBuildProjectExtension).props" Condition=" Exists('Directory$(MSBuildProjectExtension).props') " />
11
-</Project>
src/test/dtf/Directory.Build.targets
deleted
-6
@@ -1,6 +0,0 @@
1
-<?xml version="1.0" encoding="utf-8"?>
2
-<!-- 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. -->
3
-<Project>
4
- <Import Project="..\..\Directory.Build.targets" />
5
- <Import Project="Directory$(MSBuildProjectExtension).targets" Condition=" Exists('Directory$(MSBuildProjectExtension).targets') " />
6
-</Project>
src/test/test.cmd
-2
@@ -14,8 +14,6 @@
14
@call msi\test_msi.cmd %_C% %_T% || exit /b
15
@call burn\test_burn.cmd %_C% %_T% || exit /b
16
17
-msbuild -Restore dtf\DtfE2ETests.sln -p:Configuration=%_C% -nologo -m -warnaserror -bl:%_L%\dtfe2etests.binlog || exit /b
18
-
17
dotnet test wix -c %_C% --nologo -l "trx;LogFileName=%_L%\TestResults\WixToolsetTest.WixE2ETests.trx" || exit /b
18
19
@popd
src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
+3
-2
@@ -10,6 +10,7 @@ namespace WixToolset.Core.Burn.Bind
10
using WixToolset.Core.Burn.Bundles;
11
using WixToolset.Core.Burn.ExtensibilityServices;
12
using WixToolset.Data;
13
+ using WixToolset.Data.Burn;
14
using WixToolset.Data.Symbols;
15
using WixToolset.Extensibility;
16
using WixToolset.Extensibility.Services;
@@ -191,10 +192,10 @@ namespace WixToolset.Core.Burn.Bind
192
switch (customDataSymbol.Type)
193
{
194
case WixBundleCustomDataType.BootstrapperApplication:
194
- writer.WriteStartElement(elementName, BurnCommon.BADataNamespace);
195
+ writer.WriteStartElement(elementName, BurnConstants.BootstrapperApplicationDataNamespace);
196
break;
197
case WixBundleCustomDataType.BundleExtension:
197
- writer.WriteStartElement(elementName, BurnCommon.BundleExtensionDataNamespace);
198
+ writer.WriteStartElement(elementName, BurnConstants.BundleExtensionDataNamespace);
199
break;
200
default:
201
throw new NotImplementedException();
src/wix/WixToolset.Core.Burn/Bundles/BurnCommon.cs
-2
@@ -24,10 +24,8 @@ namespace WixToolset.Core.Burn.Bundles
24
public const string BurnAuthoredContainerEmbeddedIdFormat = "a{0}";
25
26
public const string BADataFileName = "BootstrapperApplicationData.xml";
27
- public const string BADataNamespace = "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData";
27
28
public const string BundleExtensionDataFileName = "BundleExtensionData.xml";
30
- public const string BundleExtensionDataNamespace = "http://wixtoolset.org/schemas/v4/BundleExtensionData";
29
30
// See WinNT.h for details about the PE format, including the
31
// structure and offsets for IMAGE_DOS_HEADER, IMAGE_NT_HEADERS32,
src/wix/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs
+1
-1
@@ -67,7 +67,7 @@ namespace WixToolset.Core.Burn.Bundles
67
{
68
writer.Formatting = Formatting.Indented;
69
writer.WriteStartDocument();
70
- writer.WriteStartElement("BootstrapperApplicationData", BurnCommon.BADataNamespace);
70
+ writer.WriteStartElement("BootstrapperApplicationData", BurnConstants.BootstrapperApplicationDataNamespace);
71
72
this.WriteBundleInfo(writer);
73
src/wix/WixToolset.Core.Burn/Bundles/CreateBundleExtensionManifestCommand.cs
+1
-1
@@ -53,7 +53,7 @@ namespace WixToolset.Core.Burn.Bundles
53
{
54
writer.Formatting = Formatting.Indented;
55
writer.WriteStartDocument();
56
- writer.WriteStartElement("BundleExtensionData", BurnCommon.BundleExtensionDataNamespace);
56
+ writer.WriteStartElement("BundleExtensionData", BurnConstants.BundleExtensionDataNamespace);
57
58
this.InternalBurnBackendHelper.WriteBundleExtensionData(writer);
59
src/wix/WixToolset.Core.Burn/ExtensibilityServices/BurnBackendHelper.cs
+3
-2
@@ -9,6 +9,7 @@ namespace WixToolset.Core.Burn.ExtensibilityServices
9
using System.Xml;
10
using WixToolset.Core.Burn.Bundles;
11
using WixToolset.Data;
12
+ using WixToolset.Data.Burn;
13
using WixToolset.Data.Symbols;
14
using WixToolset.Data.WindowsInstaller.Rows;
15
using WixToolset.Extensibility.Data;
@@ -160,7 +161,7 @@ namespace WixToolset.Core.Burn.ExtensibilityServices
161
162
public void AddBootstrapperApplicationData(IntermediateSymbol symbol, bool symbolIdIsIdAttribute = false)
163
{
163
- this.BootstrapperApplicationManifestData.AddSymbol(symbol, symbolIdIsIdAttribute, BurnCommon.BADataNamespace);
164
+ this.BootstrapperApplicationManifestData.AddSymbol(symbol, symbolIdIsIdAttribute, BurnConstants.BootstrapperApplicationDataNamespace);
165
}
166
167
public void AddBundleExtensionData(string extensionId, string xml)
@@ -172,7 +173,7 @@ namespace WixToolset.Core.Burn.ExtensibilityServices
173
public void AddBundleExtensionData(string extensionId, IntermediateSymbol symbol, bool symbolIdIsIdAttribute = false)
174
{
175
var manifestData = this.GetBundleExtensionManifestData(extensionId);
175
- manifestData.AddSymbol(symbol, symbolIdIsIdAttribute, BurnCommon.BundleExtensionDataNamespace);
176
+ manifestData.AddSymbol(symbol, symbolIdIsIdAttribute, BurnConstants.BundleExtensionDataNamespace);
177
}
178
179
#endregion
src/wix/WixToolset.Core.TestPackage/BundleExtractor.cs
+3
-2
@@ -5,6 +5,7 @@ namespace WixToolset.Core.TestPackage
5
using System.IO;
6
using System.Xml;
7
using WixToolset.Core.Burn.Bundles;
8
+ using WixToolset.Data.Burn;
9
using WixToolset.Extensibility.Services;
10
11
/// <summary>
@@ -72,7 +73,7 @@ namespace WixToolset.Core.TestPackage
73
public static XmlNamespaceManager GetBADataNamespaceManager(XmlDocument document, string prefix)
74
{
75
var namespaceManager = new XmlNamespaceManager(document.NameTable);
75
- namespaceManager.AddNamespace(prefix, BurnCommon.BADataNamespace);
76
+ namespaceManager.AddNamespace(prefix, BurnConstants.BootstrapperApplicationDataNamespace);
77
return namespaceManager;
78
}
79
@@ -85,7 +86,7 @@ namespace WixToolset.Core.TestPackage
86
public static XmlNamespaceManager GetBundleExtensionDataNamespaceManager(XmlDocument document, string prefix)
87
{
88
var namespaceManager = new XmlNamespaceManager(document.NameTable);
88
- namespaceManager.AddNamespace(prefix, BurnCommon.BundleExtensionDataNamespace);
89
+ namespaceManager.AddNamespace(prefix, BurnConstants.BundleExtensionDataNamespace);
90
return namespaceManager;
91
}
92