aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-04-13 10:13:36 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-04-13 13:13:48 -0500
commit863c1b8180d802f98e37be876b0c27efce2e8ace (patch)
treeccb73b5764ff17e1003bb6df4fa734661150e644 /src
parentbe43682720cf9c238aa1efba5940b8e2279c5bc4 (diff)
downloadwix-863c1b8180d802f98e37be876b0c27efce2e8ace.tar.gz
wix-863c1b8180d802f98e37be876b0c27efce2e8ace.tar.bz2
wix-863c1b8180d802f98e37be876b0c27efce2e8ace.zip
Create Harvested*PackageSymbols.
Diffstat (limited to 'src')
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs12
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedBundlePackageSymbol.cs134
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMsiPackageSymbol.cs174
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMspPackageSymbol.cs92
-rw-r--r--src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs3
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs158
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs369
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs108
-rw-r--r--src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs4
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs2
10 files changed, 820 insertions, 236 deletions
diff --git a/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs b/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs
index 1fd8ded1..3e0ec512 100644
--- a/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs
+++ b/src/api/wix/WixToolset.Data/Symbols/SymbolDefinitions.cs
@@ -130,6 +130,9 @@ namespace WixToolset.Data
130 WixBundleExePackage, 130 WixBundleExePackage,
131 WixBundleExePackagePayload, 131 WixBundleExePackagePayload,
132 WixBundleExtension, 132 WixBundleExtension,
133 WixBundleHarvestedBundlePackage,
134 WixBundleHarvestedMsiPackage,
135 WixBundleHarvestedMspPackage,
133 WixBundleMsiFeature, 136 WixBundleMsiFeature,
134 WixBundleMsiPackage, 137 WixBundleMsiPackage,
135 WixBundleMsiPackagePayload, 138 WixBundleMsiPackagePayload,
@@ -583,6 +586,15 @@ namespace WixToolset.Data
583 case SymbolDefinitionType.WixBundleExePackagePayload: 586 case SymbolDefinitionType.WixBundleExePackagePayload:
584 return SymbolDefinitions.WixBundleExePackagePayload; 587 return SymbolDefinitions.WixBundleExePackagePayload;
585 588
589 case SymbolDefinitionType.WixBundleHarvestedBundlePackage:
590 return SymbolDefinitions.WixBundleHarvestedBundlePackage;
591
592 case SymbolDefinitionType.WixBundleHarvestedMsiPackage:
593 return SymbolDefinitions.WixBundleHarvestedMsiPackage;
594
595 case SymbolDefinitionType.WixBundleHarvestedMspPackage:
596 return SymbolDefinitions.WixBundleHarvestedMspPackage;
597
586 case SymbolDefinitionType.WixBundleMsiFeature: 598 case SymbolDefinitionType.WixBundleMsiFeature:
587 return SymbolDefinitions.WixBundleMsiFeature; 599 return SymbolDefinitions.WixBundleMsiFeature;
588 600
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedBundlePackageSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedBundlePackageSymbol.cs
new file mode 100644
index 00000000..01e18728
--- /dev/null
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedBundlePackageSymbol.cs
@@ -0,0 +1,134 @@
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
3namespace WixToolset.Data
4{
5 using WixToolset.Data.Symbols;
6
7 public static partial class SymbolDefinitions
8 {
9 public static readonly IntermediateSymbolDefinition WixBundleHarvestedBundlePackage = new IntermediateSymbolDefinition(
10 SymbolDefinitionType.WixBundleHarvestedBundlePackage,
11 new[]
12 {
13 new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.Attributes), IntermediateFieldType.Number),
14 new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.BundleId), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.ManifestNamespace), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.ProtocolVersion), IntermediateFieldType.Number),
17 new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.Version), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.DisplayName), IntermediateFieldType.String),
19 new IntermediateFieldDefinition(nameof(WixBundleHarvestedBundlePackageSymbolFields.InstallSize), IntermediateFieldType.LargeNumber),
20 },
21 typeof(WixBundleHarvestedBundlePackageSymbol));
22 }
23}
24
25namespace WixToolset.Data.Symbols
26{
27 using System;
28
29 public enum WixBundleHarvestedBundlePackageSymbolFields
30 {
31 Attributes,
32 BundleId,
33 ManifestNamespace,
34 ProtocolVersion,
35 Version,
36 DisplayName,
37 InstallSize,
38 }
39
40 [Flags]
41 public enum WixBundleHarvestedBundlePackageAttributes
42 {
43 None = 0x0,
44 PerMachine = 0x1,
45 Win64 = 0x2,
46 }
47
48 public class WixBundleHarvestedBundlePackageSymbol : IntermediateSymbol
49 {
50 public WixBundleHarvestedBundlePackageSymbol() : base(SymbolDefinitions.WixBundleHarvestedBundlePackage, null, null)
51 {
52 }
53
54 public WixBundleHarvestedBundlePackageSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SymbolDefinitions.WixBundleHarvestedBundlePackage, sourceLineNumber, id)
55 {
56 }
57
58 public IntermediateField this[WixBundleHarvestedBundlePackageSymbolFields index] => this.Fields[(int)index];
59
60 public WixBundleHarvestedBundlePackageAttributes Attributes
61 {
62 get => (WixBundleHarvestedBundlePackageAttributes)this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.Attributes].AsNumber();
63 set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.Attributes, (int)value);
64 }
65
66 public string BundleId
67 {
68 get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.BundleId].AsString();
69 set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.BundleId, value);
70 }
71
72 public string ManifestNamespace
73 {
74 get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.ManifestNamespace].AsString();
75 set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.ManifestNamespace, value);
76 }
77
78 public int ProtocolVersion
79 {
80 get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.ProtocolVersion].AsNumber();
81 set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.ProtocolVersion, value);
82 }
83
84 public string Version
85 {
86 get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.Version].AsString();
87 set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.Version, value);
88 }
89
90 public string DisplayName
91 {
92 get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.DisplayName].AsString();
93 set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.DisplayName, value);
94 }
95
96 public long InstallSize
97 {
98 get => this.Fields[(int)WixBundleHarvestedBundlePackageSymbolFields.InstallSize].AsLargeNumber();
99 set => this.Set((int)WixBundleHarvestedBundlePackageSymbolFields.InstallSize, value);
100 }
101
102 public bool PerMachine
103 {
104 get { return this.Attributes.HasFlag(WixBundleHarvestedBundlePackageAttributes.PerMachine); }
105 set
106 {
107 if (value)
108 {
109 this.Attributes |= WixBundleHarvestedBundlePackageAttributes.PerMachine;
110 }
111 else
112 {
113 this.Attributes &= ~WixBundleHarvestedBundlePackageAttributes.PerMachine;
114 }
115 }
116 }
117
118 public bool Win64
119 {
120 get { return this.Attributes.HasFlag(WixBundleHarvestedBundlePackageAttributes.Win64); }
121 set
122 {
123 if (value)
124 {
125 this.Attributes |= WixBundleHarvestedBundlePackageAttributes.Win64;
126 }
127 else
128 {
129 this.Attributes &= ~WixBundleHarvestedBundlePackageAttributes.Win64;
130 }
131 }
132 }
133 }
134}
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMsiPackageSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMsiPackageSymbol.cs
new file mode 100644
index 00000000..8a274720
--- /dev/null
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMsiPackageSymbol.cs
@@ -0,0 +1,174 @@
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
3namespace WixToolset.Data
4{
5 using WixToolset.Data.Symbols;
6
7 public static partial class SymbolDefinitions
8 {
9 public static readonly IntermediateSymbolDefinition WixBundleHarvestedMsiPackage = new IntermediateSymbolDefinition(
10 SymbolDefinitionType.WixBundleHarvestedMsiPackage,
11 new[]
12 {
13 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.Attributes), IntermediateFieldType.Number),
14 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ProductName), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ArpComments), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.AllUsers), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.MsiFastInstall), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ArpSystemComponent), IntermediateFieldType.String),
19 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ProductCode), IntermediateFieldType.String),
20 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.UpgradeCode), IntermediateFieldType.String),
21 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.Manufacturer), IntermediateFieldType.String),
22 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ProductLanguage), IntermediateFieldType.String),
23 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.ProductVersion), IntermediateFieldType.String),
24 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMsiPackageSymbolFields.InstallSize), IntermediateFieldType.LargeNumber),
25 },
26 typeof(WixBundleHarvestedMsiPackageSymbol));
27 }
28}
29
30namespace WixToolset.Data.Symbols
31{
32 using System;
33
34 public enum WixBundleHarvestedMsiPackageSymbolFields
35 {
36 Attributes,
37 ProductName,
38 ArpComments,
39 AllUsers,
40 MsiFastInstall,
41 ArpSystemComponent,
42 ProductCode,
43 UpgradeCode,
44 Manufacturer,
45 ProductLanguage,
46 ProductVersion,
47 InstallSize,
48 }
49
50 [Flags]
51 public enum WixBundleHarvestedMsiPackageAttributes
52 {
53 None = 0x0,
54 PerMachine = 0x01,
55 Win64 = 0x2,
56 }
57
58 public class WixBundleHarvestedMsiPackageSymbol : IntermediateSymbol
59 {
60 public WixBundleHarvestedMsiPackageSymbol() : base(SymbolDefinitions.WixBundleHarvestedMsiPackage, null, null)
61 {
62 }
63
64 public WixBundleHarvestedMsiPackageSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SymbolDefinitions.WixBundleHarvestedMsiPackage, sourceLineNumber, id)
65 {
66 }
67
68 public IntermediateField this[WixBundleHarvestedMsiPackageSymbolFields index] => this.Fields[(int)index];
69
70 public WixBundleHarvestedMsiPackageAttributes Attributes
71 {
72 get => (WixBundleHarvestedMsiPackageAttributes)this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.Attributes].AsNumber();
73 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.Attributes, (int)value);
74 }
75
76 public string ProductName
77 {
78 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ProductName].AsString();
79 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ProductName, value);
80 }
81
82 public string ArpComments
83 {
84 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ArpComments].AsString();
85 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ArpComments, value);
86 }
87
88 public string AllUsers
89 {
90 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.AllUsers].AsString();
91 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.AllUsers, value);
92 }
93
94 public string MsiFastInstall
95 {
96 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.MsiFastInstall].AsString();
97 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.MsiFastInstall, value);
98 }
99
100 public string ArpSystemComponent
101 {
102 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ArpSystemComponent].AsString();
103 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ArpSystemComponent, value);
104 }
105
106 public string ProductCode
107 {
108 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ProductCode].AsString();
109 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ProductCode, value);
110 }
111
112 public string UpgradeCode
113 {
114 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.UpgradeCode].AsString();
115 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.UpgradeCode, value);
116 }
117
118 public string Manufacturer
119 {
120 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.Manufacturer].AsString();
121 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.Manufacturer, value);
122 }
123
124 public string ProductLanguage
125 {
126 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ProductLanguage].AsString();
127 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ProductLanguage, value);
128 }
129
130 public string ProductVersion
131 {
132 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.ProductVersion].AsString();
133 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.ProductVersion, value);
134 }
135
136 public long InstallSize
137 {
138 get => this.Fields[(int)WixBundleHarvestedMsiPackageSymbolFields.InstallSize].AsLargeNumber();
139 set => this.Set((int)WixBundleHarvestedMsiPackageSymbolFields.InstallSize, value);
140 }
141
142 public bool PerMachine
143 {
144 get { return this.Attributes.HasFlag(WixBundleHarvestedMsiPackageAttributes.PerMachine); }
145 set
146 {
147 if (value)
148 {
149 this.Attributes |= WixBundleHarvestedMsiPackageAttributes.PerMachine;
150 }
151 else
152 {
153 this.Attributes &= ~WixBundleHarvestedMsiPackageAttributes.PerMachine;
154 }
155 }
156 }
157
158 public bool Win64
159 {
160 get { return this.Attributes.HasFlag(WixBundleHarvestedMsiPackageAttributes.Win64); }
161 set
162 {
163 if (value)
164 {
165 this.Attributes |= WixBundleHarvestedMsiPackageAttributes.Win64;
166 }
167 else
168 {
169 this.Attributes &= ~WixBundleHarvestedMsiPackageAttributes.Win64;
170 }
171 }
172 }
173 }
174}
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMspPackageSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMspPackageSymbol.cs
new file mode 100644
index 00000000..43bcc763
--- /dev/null
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleHarvestedMspPackageSymbol.cs
@@ -0,0 +1,92 @@
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
3namespace WixToolset.Data
4{
5 using WixToolset.Data.Symbols;
6
7 public static partial class SymbolDefinitions
8 {
9 public static readonly IntermediateSymbolDefinition WixBundleHarvestedMspPackage = new IntermediateSymbolDefinition(
10 SymbolDefinitionType.WixBundleHarvestedMspPackage,
11 new[]
12 {
13 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.Attributes), IntermediateFieldType.Number),
14 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.PatchCode), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.DisplayName), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.Description), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.ManufacturerName), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(WixBundleHarvestedMspPackageSymbolFields.PatchXml), IntermediateFieldType.String),
19 },
20 typeof(WixBundleHarvestedMspPackageSymbol));
21 }
22}
23
24namespace WixToolset.Data.Symbols
25{
26 using System;
27
28 public enum WixBundleHarvestedMspPackageSymbolFields
29 {
30 Attributes,
31 PatchCode,
32 DisplayName,
33 Description,
34 ManufacturerName,
35 PatchXml,
36 }
37
38 [Flags]
39 public enum WixBundleHarvestedMspPackageAttributes
40 {
41 None = 0x0,
42 }
43
44 public class WixBundleHarvestedMspPackageSymbol : IntermediateSymbol
45 {
46 public WixBundleHarvestedMspPackageSymbol() : base(SymbolDefinitions.WixBundleHarvestedMspPackage, null, null)
47 {
48 }
49
50 public WixBundleHarvestedMspPackageSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SymbolDefinitions.WixBundleHarvestedMspPackage, sourceLineNumber, id)
51 {
52 }
53
54 public IntermediateField this[WixBundleHarvestedMspPackageSymbolFields index] => this.Fields[(int)index];
55
56 public WixBundleHarvestedMspPackageAttributes Attributes
57 {
58 get => (WixBundleHarvestedMspPackageAttributes)this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.Attributes].AsNumber();
59 set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.Attributes, (int)value);
60 }
61
62 public string PatchCode
63 {
64 get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.PatchCode].AsString();
65 set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.PatchCode, value);
66 }
67
68 public string DisplayName
69 {
70 get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.DisplayName].AsString();
71 set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.DisplayName, value);
72 }
73
74 public string Description
75 {
76 get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.Description].AsString();
77 set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.Description, value);
78 }
79
80 public string ManufacturerName
81 {
82 get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.ManufacturerName].AsString();
83 set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.ManufacturerName, value);
84 }
85
86 public string PatchXml
87 {
88 get => this.Fields[(int)WixBundleHarvestedMspPackageSymbolFields.PatchXml].AsString();
89 set => this.Set((int)WixBundleHarvestedMspPackageSymbolFields.PatchXml, value);
90 }
91 }
92}
diff --git a/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
index 396e0eff..610bdd75 100644
--- a/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
@@ -70,6 +70,9 @@ namespace WixToolset.Core.Burn.Bind
70 case SymbolDefinitionType.WixBundleExePackage: 70 case SymbolDefinitionType.WixBundleExePackage:
71 case SymbolDefinitionType.WixBundleExePackagePayload: 71 case SymbolDefinitionType.WixBundleExePackagePayload:
72 case SymbolDefinitionType.WixBundleExtension: 72 case SymbolDefinitionType.WixBundleExtension:
73 case SymbolDefinitionType.WixBundleHarvestedBundlePackage:
74 case SymbolDefinitionType.WixBundleHarvestedMsiPackage:
75 case SymbolDefinitionType.WixBundleHarvestedMspPackage:
73 case SymbolDefinitionType.WixBundleMsiFeature: 76 case SymbolDefinitionType.WixBundleMsiFeature:
74 case SymbolDefinitionType.WixBundleMsiPackage: 77 case SymbolDefinitionType.WixBundleMsiPackage:
75 case SymbolDefinitionType.WixBundleMsiPackagePayload: 78 case SymbolDefinitionType.WixBundleMsiPackagePayload:
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
index aed005ba..2abdec06 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessBundlePackageCommand.cs
@@ -6,6 +6,7 @@ namespace WixToolset.Core.Burn.Bundles
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Diagnostics; 7 using System.Diagnostics;
8 using System.IO; 8 using System.IO;
9 using System.Linq;
9 using System.Xml; 10 using System.Xml;
10 using WixToolset.Data; 11 using WixToolset.Data;
11 using WixToolset.Data.Symbols; 12 using WixToolset.Data.Symbols;
@@ -23,8 +24,11 @@ namespace WixToolset.Core.Burn.Bundles
23 this.BackendHelper = serviceProvider.GetService<IBackendHelper>(); 24 this.BackendHelper = serviceProvider.GetService<IBackendHelper>();
24 this.PackagePayloads = packagePayloads; 25 this.PackagePayloads = packagePayloads;
25 this.Section = section; 26 this.Section = section;
26 this.Facade = facade;
27 this.IntermediateFolder = intermediateFolder; 27 this.IntermediateFolder = intermediateFolder;
28
29 this.ChainPackage = facade.PackageSymbol;
30 this.BundlePackage = (WixBundleBundlePackageSymbol)facade.SpecificPackageSymbol;
31 this.PackagePayload = packagePayloads[this.ChainPackage.PayloadRef];
28 } 32 }
29 33
30 private IMessaging Messaging { get; } 34 private IMessaging Messaging { get; }
@@ -33,7 +37,13 @@ namespace WixToolset.Core.Burn.Bundles
33 37
34 private Dictionary<string, WixBundlePayloadSymbol> PackagePayloads { get; } 38 private Dictionary<string, WixBundlePayloadSymbol> PackagePayloads { get; }
35 39
36 private PackageFacade Facade { get; } 40 private WixBundlePackageSymbol ChainPackage { get; }
41
42 private WixBundleBundlePackageSymbol BundlePackage { get; }
43
44 private string PackageId => this.ChainPackage.Id.Id;
45
46 private WixBundlePayloadSymbol PackagePayload { get; }
37 47
38 private IntermediateSection Section { get; } 48 private IntermediateSection Section { get; }
39 49
@@ -46,27 +56,81 @@ namespace WixToolset.Core.Burn.Bundles
46 /// </summary> 56 /// </summary>
47 public void Execute() 57 public void Execute()
48 { 58 {
49 var bundlePackage = (WixBundleBundlePackageSymbol)this.Facade.SpecificPackageSymbol; 59 var harvestedBundlePackage = this.Section.Symbols.OfType<WixBundleHarvestedBundlePackageSymbol>()
50 var packagePayload = this.PackagePayloads[this.Facade.PackageSymbol.PayloadRef]; 60 .Where(h => h.Id == this.ChainPackage.Id)
51 var sourcePath = packagePayload.SourceFile.Path; 61 .SingleOrDefault();
62
63 if (harvestedBundlePackage == null)
64 {
65 harvestedBundlePackage = this.HarvestPackage();
66
67 if (harvestedBundlePackage == null)
68 {
69 return;
70 }
71 }
72
73 this.ChainPackage.Win64 = harvestedBundlePackage.Win64;
74 this.BundlePackage.BundleId = Guid.Parse(harvestedBundlePackage.BundleId).ToString("B").ToUpperInvariant();
75 this.BundlePackage.SupportsBurnProtocol = harvestedBundlePackage.ProtocolVersion == 1; // Keep in sync with burn\engine\inc\engine.h
76
77 var supportsArpSystemComponent = BurnCommon.BurnV3Namespace != harvestedBundlePackage.ManifestNamespace;
78 if (!supportsArpSystemComponent && !this.ChainPackage.Visible)
79 {
80 this.Messaging.Write(BurnBackendWarnings.HiddenBundleNotSupported(this.PackagePayload.SourceLineNumbers, this.PackageId));
81
82 this.ChainPackage.Visible = true;
83 }
84
85 this.ChainPackage.PerMachine = harvestedBundlePackage.PerMachine;
86 this.PackagePayload.Version = harvestedBundlePackage.Version;
87 this.BundlePackage.Version = harvestedBundlePackage.Version;
88 this.ChainPackage.Version = harvestedBundlePackage.Version;
89
90 if (String.IsNullOrEmpty(this.ChainPackage.CacheId))
91 {
92 this.ChainPackage.CacheId = String.Format("{0}v{1}", this.BundlePackage.BundleId, this.BundlePackage.Version);
93 }
94
95 if (String.IsNullOrEmpty(this.ChainPackage.DisplayName))
96 {
97 this.ChainPackage.DisplayName = harvestedBundlePackage.DisplayName;
98 }
99
100 this.ChainPackage.InstallSize = harvestedBundlePackage.InstallSize;
101 }
102
103 public WixBundleHarvestedBundlePackageSymbol HarvestPackage()
104 {
105 bool win64;
106 string bundleId;
107 int protocolVersion;
108 string manifestNamespace;
109 bool perMachine;
110 string version;
111 string displayName;
112 long installSize;
113
114 var sourcePath = this.PackagePayload.SourceFile.Path;
115 var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
52 116
53 using (var burnReader = BurnReader.Open(this.Messaging, sourcePath)) 117 using (var burnReader = BurnReader.Open(this.Messaging, sourcePath))
54 { 118 {
55 if (burnReader.Invalid) 119 if (burnReader.Invalid)
56 { 120 {
57 return; 121 return null;
58 } 122 }
59 123
60 var baFolderPath = Path.Combine(this.IntermediateFolder, burnReader.BundleId.ToString()); 124 var baFolderPath = Path.Combine(this.IntermediateFolder, burnReader.BundleId.ToString());
61 125
62 if (!burnReader.ExtractUXContainer(baFolderPath, baFolderPath)) 126 if (!burnReader.ExtractUXContainer(baFolderPath, baFolderPath))
63 { 127 {
64 return; 128 return null;
65 } 129 }
66 130
67 foreach (var filePath in Directory.EnumerateFiles(baFolderPath, "*.*", SearchOption.AllDirectories)) 131 foreach (var filePath in Directory.EnumerateFiles(baFolderPath, "*.*", SearchOption.AllDirectories))
68 { 132 {
69 this.TrackedFiles.Add(this.BackendHelper.TrackFile(filePath, TrackedFileType.Temporary, packagePayload.SourceLineNumbers)); 133 this.TrackedFiles.Add(this.BackendHelper.TrackFile(filePath, TrackedFileType.Temporary, sourceLineNumbers));
70 } 134 }
71 135
72 switch (burnReader.MachineType) 136 switch (burnReader.MachineType)
@@ -77,12 +141,13 @@ namespace WixToolset.Core.Burn.Bundles
77 case BurnCommon.IMAGE_FILE_MACHINE_I386: 141 case BurnCommon.IMAGE_FILE_MACHINE_I386:
78 case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH32: 142 case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH32:
79 case BurnCommon.IMAGE_FILE_MACHINE_M32R: 143 case BurnCommon.IMAGE_FILE_MACHINE_M32R:
144 win64 = false;
80 break; 145 break;
81 case BurnCommon.IMAGE_FILE_MACHINE_AMD64: 146 case BurnCommon.IMAGE_FILE_MACHINE_AMD64:
82 case BurnCommon.IMAGE_FILE_MACHINE_ARM64: 147 case BurnCommon.IMAGE_FILE_MACHINE_ARM64:
83 case BurnCommon.IMAGE_FILE_MACHINE_IA64: 148 case BurnCommon.IMAGE_FILE_MACHINE_IA64:
84 case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH64: 149 case BurnCommon.IMAGE_FILE_MACHINE_LOONGARCH64:
85 this.Facade.PackageSymbol.Win64 = true; 150 win64 = true;
86 break; 151 break;
87 case BurnCommon.IMAGE_FILE_MACHINE_EBC: 152 case BurnCommon.IMAGE_FILE_MACHINE_EBC:
88 case BurnCommon.IMAGE_FILE_MACHINE_MIPS16: 153 case BurnCommon.IMAGE_FILE_MACHINE_MIPS16:
@@ -101,15 +166,16 @@ namespace WixToolset.Core.Burn.Bundles
101 case BurnCommon.IMAGE_FILE_MACHINE_THUMB: 166 case BurnCommon.IMAGE_FILE_MACHINE_THUMB:
102 case BurnCommon.IMAGE_FILE_MACHINE_WCEMIPSV2: 167 case BurnCommon.IMAGE_FILE_MACHINE_WCEMIPSV2:
103 default: 168 default:
104 this.Messaging.Write(BurnBackendWarnings.UnknownCoffMachineType(packagePayload.SourceLineNumbers, sourcePath, burnReader.MachineType)); 169 win64 = false;
170 this.Messaging.Write(BurnBackendWarnings.UnknownCoffMachineType(sourceLineNumbers, sourcePath, burnReader.MachineType));
105 break; 171 break;
106 } 172 }
107 173
108 bundlePackage.BundleId = burnReader.BundleId.ToString("B").ToUpperInvariant(); 174 bundleId = burnReader.BundleId.ToString("B").ToUpperInvariant();
109 175
110 // Assume that the .wixburn section version will change when the Burn protocol changes. 176 // Assume that the .wixburn section version will change when the Burn protocol changes.
111 // This should be a safe assumption since we will need to add the protocol version to the section to support this harvesting. 177 // This should be a safe assumption since we will need to add the protocol version to the section to support this harvesting.
112 bundlePackage.SupportsBurnProtocol = burnReader.Version == 2; 178 protocolVersion = burnReader.Version == 2 ? 1 : 0;
113 179
114 try 180 try
115 { 181 {
@@ -119,63 +185,59 @@ namespace WixToolset.Core.Burn.Bundles
119 185
120 if (document.DocumentElement.LocalName != "BurnManifest") 186 if (document.DocumentElement.LocalName != "BurnManifest")
121 { 187 {
122 this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(packagePayload.SourceLineNumbers, sourcePath, $"Expected root element to be 'Manifest' but was '{document.DocumentElement.LocalName}'.")); 188 this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, $"Expected root element to be 'BurnManifest' but was '{document.DocumentElement.LocalName}'."));
123 return; 189 return null;
124 } 190 }
125 191
126 if (BurnCommon.BurnV3Namespace == document.DocumentElement.NamespaceURI && !this.Facade.PackageSymbol.Visible) 192 manifestNamespace = document.DocumentElement.NamespaceURI;
127 {
128 this.Messaging.Write(BurnBackendWarnings.HiddenBundleNotSupported(packagePayload.SourceLineNumbers, sourcePath));
129
130 this.Facade.PackageSymbol.Visible = true;
131 }
132 193
133 namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI); 194 namespaceManager.AddNamespace("burn", document.DocumentElement.NamespaceURI);
134 var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement; 195 var registrationElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration", namespaceManager) as XmlElement;
135 var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement; 196 var arpElement = document.SelectSingleNode("/burn:BurnManifest/burn:Registration/burn:Arp", namespaceManager) as XmlElement;
136 197
137 var perMachine = registrationElement.GetAttribute("PerMachine") == "yes"; 198 perMachine = registrationElement.GetAttribute("PerMachine") == "yes";
138 this.Facade.PackageSymbol.PerMachine = perMachine;
139
140 var version = registrationElement.GetAttribute("Version");
141 packagePayload.Version = version;
142 bundlePackage.Version = version;
143 this.Facade.PackageSymbol.Version = version;
144 199
145 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.CacheId)) 200 version = registrationElement.GetAttribute("Version");
146 {
147 this.Facade.PackageSymbol.CacheId = String.Format("{0}v{1}", bundlePackage.BundleId, version);
148 }
149 201
150 var providerKey = registrationElement.GetAttribute("ProviderKey"); 202 var providerKey = registrationElement.GetAttribute("ProviderKey");
151 var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", bundlePackage.Id.Id, providerKey)); 203 var depId = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackageId, providerKey));
152 this.Section.AddSymbol(new WixDependencyProviderSymbol(packagePayload.SourceLineNumbers, depId) 204 this.Section.AddSymbol(new WixDependencyProviderSymbol(sourceLineNumbers, depId)
153 { 205 {
154 ParentRef = bundlePackage.Id.Id, 206 ParentRef = this.PackageId,
155 ProviderKey = providerKey, 207 ProviderKey = providerKey,
156 Version = version, 208 Version = version,
157 Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported, 209 Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported,
158 }); 210 });
159 211
160 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) 212 displayName = arpElement.GetAttribute("DisplayName");
161 {
162 this.Facade.PackageSymbol.DisplayName = arpElement.GetAttribute("DisplayName");
163 }
164 213
165 this.ProcessPackages(document, namespaceManager); 214 installSize = this.ProcessPackages(document, namespaceManager);
166 215
167 this.ProcessRelatedBundles(document, namespaceManager, packagePayload, sourcePath); 216 this.ProcessRelatedBundles(document, namespaceManager, sourcePath);
168 217
169 // TODO: Add payloads? 218 // TODO: Add payloads?
170 } 219 }
171 catch (Exception e) 220 catch (Exception e)
172 { 221 {
173 this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(packagePayload.SourceLineNumbers, sourcePath, e.ToString())); 222 this.Messaging.Write(BurnBackendErrors.InvalidBundleManifest(sourceLineNumbers, sourcePath, e.ToString()));
223 return null;
174 } 224 }
175 } 225 }
226
227 return this.Section.AddSymbol(new WixBundleHarvestedBundlePackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id)
228 {
229 Win64 = win64,
230 BundleId = bundleId,
231 ManifestNamespace = manifestNamespace,
232 ProtocolVersion = protocolVersion,
233 PerMachine = perMachine,
234 Version = version,
235 DisplayName = displayName,
236 InstallSize = installSize,
237 });
176 } 238 }
177 239
178 private void ProcessPackages(XmlDocument document, XmlNamespaceManager namespaceManager) 240 private long ProcessPackages(XmlDocument document, XmlNamespaceManager namespaceManager)
179 { 241 {
180 long packageInstallSize = 0; 242 long packageInstallSize = 0;
181 243
@@ -192,11 +254,13 @@ namespace WixToolset.Core.Burn.Bundles
192 } 254 }
193 } 255 }
194 256
195 this.Facade.PackageSymbol.InstallSize = packageInstallSize; 257 return packageInstallSize;
196 } 258 }
197 259
198 private void ProcessRelatedBundles(XmlDocument document, XmlNamespaceManager namespaceManager, WixBundlePayloadSymbol packagePayload, string sourcePath) 260 private void ProcessRelatedBundles(XmlDocument document, XmlNamespaceManager namespaceManager, string sourcePath)
199 { 261 {
262 var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
263
200 foreach (XmlElement relatedBundleElement in document.SelectNodes("/burn:BurnManifest/burn:RelatedBundle", namespaceManager)) 264 foreach (XmlElement relatedBundleElement in document.SelectNodes("/burn:BurnManifest/burn:RelatedBundle", namespaceManager))
201 { 265 {
202 var id = relatedBundleElement.GetAttribute("Id"); 266 var id = relatedBundleElement.GetAttribute("Id");
@@ -204,13 +268,13 @@ namespace WixToolset.Core.Burn.Bundles
204 268
205 if (!Enum.TryParse(actionValue, out RelatedBundleActionType action)) 269 if (!Enum.TryParse(actionValue, out RelatedBundleActionType action))
206 { 270 {
207 this.Messaging.Write(BurnBackendWarnings.UnknownBundleRelationAction(packagePayload.SourceLineNumbers, sourcePath, actionValue)); 271 this.Messaging.Write(BurnBackendWarnings.UnknownBundleRelationAction(sourceLineNumbers, sourcePath, actionValue));
208 continue; 272 continue;
209 } 273 }
210 274
211 this.Section.AddSymbol(new WixBundlePackageRelatedBundleSymbol 275 this.Section.AddSymbol(new WixBundlePackageRelatedBundleSymbol(sourceLineNumbers)
212 { 276 {
213 PackageRef = this.Facade.PackageId, 277 PackageRef = this.PackageId,
214 BundleId = id, 278 BundleId = id,
215 Action = action, 279 Action = action,
216 }); 280 });
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs
index 4ca3a730..5acec2a4 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs
@@ -33,7 +33,10 @@ namespace WixToolset.Core.Burn.Bundles
33 33
34 this.PackagePayloads = packagePayloads; 34 this.PackagePayloads = packagePayloads;
35 this.Section = section; 35 this.Section = section;
36 this.Facade = facade; 36
37 this.ChainPackage = facade.PackageSymbol;
38 this.MsiPackage = (WixBundleMsiPackageSymbol)facade.SpecificPackageSymbol;
39 this.PackagePayload = packagePayloads[this.ChainPackage.PayloadRef];
37 } 40 }
38 41
39 private IMessaging Messaging { get; } 42 private IMessaging Messaging { get; }
@@ -46,7 +49,13 @@ namespace WixToolset.Core.Burn.Bundles
46 49
47 private Dictionary<string, WixBundlePayloadSymbol> PackagePayloads { get; } 50 private Dictionary<string, WixBundlePayloadSymbol> PackagePayloads { get; }
48 51
49 private PackageFacade Facade { get; } 52 private WixBundlePackageSymbol ChainPackage { get; }
53
54 private WixBundleMsiPackageSymbol MsiPackage { get; }
55
56 private string PackageId => this.ChainPackage.Id.Id;
57
58 private WixBundlePayloadSymbol PackagePayload { get; }
50 59
51 private IntermediateSection Section { get; } 60 private IntermediateSection Section { get; }
52 61
@@ -55,16 +64,115 @@ namespace WixToolset.Core.Burn.Bundles
55 /// </summary> 64 /// </summary>
56 public void Execute() 65 public void Execute()
57 { 66 {
58 var packagePayload = this.PackagePayloads[this.Facade.PackageSymbol.PayloadRef]; 67 var harvestedMsiPackage = this.Section.Symbols.OfType<WixBundleHarvestedMsiPackageSymbol>()
68 .Where(h => h.Id == this.ChainPackage.Id)
69 .SingleOrDefault();
70
71 if (harvestedMsiPackage == null)
72 {
73 harvestedMsiPackage = this.HarvestPackage();
74
75 if (harvestedMsiPackage == null)
76 {
77 return;
78 }
79 }
80
81 this.ChainPackage.PerMachine = harvestedMsiPackage.PerMachine;
82 this.ChainPackage.Win64 = harvestedMsiPackage.Win64;
83
84 this.MsiPackage.ProductCode = harvestedMsiPackage.ProductCode;
85 this.MsiPackage.UpgradeCode = harvestedMsiPackage.UpgradeCode;
86 this.MsiPackage.Manufacturer = harvestedMsiPackage.Manufacturer;
87 this.MsiPackage.ProductLanguage = Convert.ToInt32(harvestedMsiPackage.ProductLanguage, CultureInfo.InvariantCulture);
88 this.MsiPackage.ProductVersion = harvestedMsiPackage.ProductVersion;
89
90 if (String.IsNullOrEmpty(this.ChainPackage.CacheId))
91 {
92 this.ChainPackage.CacheId = String.Format("{0}v{1}", this.MsiPackage.ProductCode, this.MsiPackage.ProductVersion);
93 }
94
95 if (String.IsNullOrEmpty(this.ChainPackage.DisplayName))
96 {
97 this.ChainPackage.DisplayName = harvestedMsiPackage.ProductName;
98 }
99
100 if (String.IsNullOrEmpty(this.ChainPackage.Description))
101 {
102 this.ChainPackage.Description = harvestedMsiPackage.ArpComments;
103 }
104
105 if (String.IsNullOrEmpty(this.ChainPackage.Version))
106 {
107 this.ChainPackage.Version = this.MsiPackage.ProductVersion;
108 }
109
110 if (!this.BackendHelper.IsValidFourPartVersion(this.MsiPackage.ProductVersion))
111 {
112 // not a proper .NET version (e.g., five fields); can we get a valid four-part version number?
113 string version = null;
114 var versionParts = this.MsiPackage.ProductVersion.Split('.');
115 var count = versionParts.Length;
116 if (0 < count)
117 {
118 version = versionParts[0];
119 for (var i = 1; i < 4 && i < count; ++i)
120 {
121 version = String.Concat(version, ".", versionParts[i]);
122 }
123 }
124
125 if (!String.IsNullOrEmpty(version) && this.BackendHelper.IsValidFourPartVersion(version))
126 {
127 this.Messaging.Write(WarningMessages.VersionTruncated(this.PackagePayload.SourceLineNumbers, this.MsiPackage.ProductVersion, this.PackageId, version));
128 this.MsiPackage.ProductVersion = version;
129 }
130 else
131 {
132 this.Messaging.Write(ErrorMessages.InvalidProductVersion(this.PackagePayload.SourceLineNumbers, this.MsiPackage.ProductVersion, this.PackageId));
133 }
134 }
135
136 this.SetPerMachineAppropriately(harvestedMsiPackage.AllUsers);
137
138 var msiPropertyNames = this.GetMsiPropertyNames();
139
140 // Ensure the MSI package is appropriately marked visible or not.
141 this.SetPackageVisibility(harvestedMsiPackage.ArpSystemComponent, msiPropertyNames);
142
143 // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance.
144 if (String.IsNullOrEmpty(harvestedMsiPackage.MsiFastInstall) && !msiPropertyNames.Contains("MSIFASTINSTALL"))
145 {
146 this.AddMsiProperty("MSIFASTINSTALL", "7");
147 }
148
149 this.ChainPackage.InstallSize = harvestedMsiPackage.InstallSize;
150 }
59 151
60 var msiPackage = (WixBundleMsiPackageSymbol)this.Facade.SpecificPackageSymbol; 152 public WixBundleHarvestedMsiPackageSymbol HarvestPackage()
153 {
154 bool perMachine;
155 bool win64;
156 string productName;
157 string arpComments;
158 string allUsers;
159 string msiFastInstall;
160 string arpSystemComponent;
161 string productCode;
162 string upgradeCode;
163 string manufacturer;
164 string productLanguage;
165 string productVersion;
166 long installSize;
167
168 var sourcePath = this.PackagePayload.SourceFile.Path;
61 169
62 var sourcePath = packagePayload.SourceFile.Path;
63 var longNamesInImage = false;
64 var compressed = false;
65 try 170 try
66 { 171 {
67 this.CheckIfWindowsInstallerFileTooLarge(packagePayload.SourceLineNumbers, sourcePath, "MSI"); 172 var longNamesInImage = false;
173 var compressed = false;
174
175 this.CheckIfWindowsInstallerFileTooLarge(this.PackagePayload.SourceLineNumbers, sourcePath, "MSI");
68 176
69 using (var db = new Database(sourcePath, OpenDatabase.ReadOnly)) 177 using (var db = new Database(sourcePath, OpenDatabase.ReadOnly))
70 { 178 {
@@ -87,117 +195,68 @@ namespace WixToolset.Core.Burn.Bundles
87 // 8 is the Word Count summary information stream bit that means 195 // 8 is the Word Count summary information stream bit that means
88 // "Elevated privileges are not required to install this package." 196 // "Elevated privileges are not required to install this package."
89 // in MSI 4.5 and below, if this bit is 0, elevation is required. 197 // in MSI 4.5 and below, if this bit is 0, elevation is required.
90 var perMachine = (0 == (fileAndElevateFlags & 8)); 198 perMachine = (0 == (fileAndElevateFlags & 8));
91 199 win64 = this.IsWin64(sourcePath, platformsAndLanguages);
92 this.Facade.PackageSymbol.PerMachine = perMachine;
93 this.Facade.PackageSymbol.Win64 = this.IsWin64(packagePayload.SourceLineNumbers, sourcePath, platformsAndLanguages);
94 } 200 }
95 201
96 string packageName = null;
97 string packageDescription = null;
98 string allusers = null;
99 string fastInstall = null;
100 string systemComponent = null;
101
102 using (var view = db.OpenView(PropertySqlQuery)) 202 using (var view = db.OpenView(PropertySqlQuery))
103 { 203 {
104 packageName = ProcessMsiPackageCommand.GetProperty(view, "ProductName"); 204 productName = ProcessMsiPackageCommand.GetProperty(view, "ProductName");
105 packageDescription = ProcessMsiPackageCommand.GetProperty(view, "ARPCOMMENTS"); 205 arpComments = ProcessMsiPackageCommand.GetProperty(view, "ARPCOMMENTS");
106 allusers = ProcessMsiPackageCommand.GetProperty(view, "ALLUSERS"); 206 allUsers = ProcessMsiPackageCommand.GetProperty(view, "ALLUSERS");
107 fastInstall = ProcessMsiPackageCommand.GetProperty(view, "MSIFASTINSTALL"); 207 msiFastInstall = ProcessMsiPackageCommand.GetProperty(view, "MSIFASTINSTALL");
108 systemComponent = ProcessMsiPackageCommand.GetProperty(view, "ARPSYSTEMCOMPONENT"); 208 arpSystemComponent = ProcessMsiPackageCommand.GetProperty(view, "ARPSYSTEMCOMPONENT");
109 209
110 msiPackage.ProductCode = ProcessMsiPackageCommand.GetProperty(view, "ProductCode"); 210 productCode = ProcessMsiPackageCommand.GetProperty(view, "ProductCode");
111 msiPackage.UpgradeCode = ProcessMsiPackageCommand.GetProperty(view, "UpgradeCode"); 211 upgradeCode = ProcessMsiPackageCommand.GetProperty(view, "UpgradeCode");
112 msiPackage.Manufacturer = ProcessMsiPackageCommand.GetProperty(view, "Manufacturer"); 212 manufacturer = ProcessMsiPackageCommand.GetProperty(view, "Manufacturer");
113 msiPackage.ProductLanguage = Convert.ToInt32(ProcessMsiPackageCommand.GetProperty(view, "ProductLanguage"), CultureInfo.InvariantCulture); 213 productLanguage = ProcessMsiPackageCommand.GetProperty(view, "ProductLanguage");
114 msiPackage.ProductVersion = ProcessMsiPackageCommand.GetProperty(view, "ProductVersion"); 214 productVersion = ProcessMsiPackageCommand.GetProperty(view, "ProductVersion");
115 }
116
117 if (!this.BackendHelper.IsValidFourPartVersion(msiPackage.ProductVersion))
118 {
119 // not a proper .NET version (e.g., five fields); can we get a valid four-part version number?
120 string version = null;
121 var versionParts = msiPackage.ProductVersion.Split('.');
122 var count = versionParts.Length;
123 if (0 < count)
124 {
125 version = versionParts[0];
126 for (var i = 1; i < 4 && i < count; ++i)
127 {
128 version = String.Concat(version, ".", versionParts[i]);
129 }
130 }
131
132 if (!String.IsNullOrEmpty(version) && this.BackendHelper.IsValidFourPartVersion(version))
133 {
134 this.Messaging.Write(WarningMessages.VersionTruncated(this.Facade.PackageSymbol.SourceLineNumbers, msiPackage.ProductVersion, sourcePath, version));
135 msiPackage.ProductVersion = version;
136 }
137 else
138 {
139 this.Messaging.Write(ErrorMessages.InvalidProductVersion(this.Facade.PackageSymbol.SourceLineNumbers, msiPackage.ProductVersion, sourcePath));
140 }
141 }
142
143 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.CacheId))
144 {
145 this.Facade.PackageSymbol.CacheId = String.Format("{0}v{1}", msiPackage.ProductCode, msiPackage.ProductVersion);
146 }
147
148 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName))
149 {
150 this.Facade.PackageSymbol.DisplayName = packageName;
151 }
152
153 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Description))
154 {
155 this.Facade.PackageSymbol.Description = packageDescription;
156 }
157
158 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Version))
159 {
160 this.Facade.PackageSymbol.Version = msiPackage.ProductVersion;
161 } 215 }
162 216
163 var payloadNames = this.GetPayloadTargetNames(); 217 var payloadNames = this.GetPayloadTargetNames();
164 218
165 var msiPropertyNames = this.GetMsiPropertyNames(packagePayload.Id.Id);
166
167 this.SetPerMachineAppropriately(allusers, msiPackage, sourcePath);
168
169 // Ensure the MSI package is appropriately marked visible or not.
170 this.SetPackageVisibility(systemComponent, msiPackage, msiPropertyNames);
171
172 // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance.
173 if (String.IsNullOrEmpty(fastInstall) && !msiPropertyNames.Contains("MSIFASTINSTALL"))
174 {
175 this.AddMsiProperty(msiPackage, "MSIFASTINSTALL", "7");
176 }
177
178 this.CreateRelatedPackages(db); 219 this.CreateRelatedPackages(db);
179 220
180 // If feature selection is enabled, represent the Feature table in the manifest. 221 // If feature selection is enabled, represent the Feature table in the manifest.
181 if (msiPackage.EnableFeatureSelection) 222 if (this.MsiPackage.EnableFeatureSelection)
182 { 223 {
183 this.CreateMsiFeatures(db); 224 this.CreateMsiFeatures(db);
184 } 225 }
185 226
186 // Add all external cabinets as package payloads. 227 // Add all external cabinets as package payloads.
187 this.ImportExternalCabinetAsPayloads(db, packagePayload, payloadNames); 228 this.ImportExternalCabinetAsPayloads(db, payloadNames);
188 229
189 // Add all external files as package payloads and calculate the total install size as the rollup of 230 // Add all external files as package payloads and calculate the total install size as the rollup of
190 // File table's sizes. 231 // File table's sizes.
191 this.Facade.PackageSymbol.InstallSize = this.ImportExternalFileAsPayloadsAndReturnInstallSize(db, packagePayload, longNamesInImage, compressed, payloadNames); 232 installSize = this.ImportExternalFileAsPayloadsAndReturnInstallSize(db, longNamesInImage, compressed, payloadNames);
192 233
193 // Add all dependency providers from the MSI. 234 // Add all dependency providers from the MSI.
194 this.ImportDependencyProviders(db, msiPackage); 235 this.ImportDependencyProviders(db);
195 } 236 }
196 } 237 }
197 catch (MsiException e) 238 catch (MsiException e)
198 { 239 {
199 this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath, e.Message)); 240 this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(this.PackagePayload.SourceLineNumbers, sourcePath, e.Message));
241 return null;
200 } 242 }
243
244 return this.Section.AddSymbol(new WixBundleHarvestedMsiPackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id)
245 {
246 PerMachine = perMachine,
247 Win64 = win64,
248 ProductName = productName,
249 ArpComments = arpComments,
250 AllUsers = allUsers,
251 MsiFastInstall = msiFastInstall,
252 ArpSystemComponent = arpSystemComponent,
253 ProductCode = productCode,
254 UpgradeCode = upgradeCode,
255 Manufacturer = manufacturer,
256 ProductLanguage = productLanguage,
257 ProductVersion = productVersion,
258 InstallSize = installSize,
259 });
201 } 260 }
202 261
203 private ISet<string> GetPayloadTargetNames() 262 private ISet<string> GetPayloadTargetNames()
@@ -207,17 +266,17 @@ namespace WixToolset.Core.Burn.Bundles
207 return new HashSet<string>(payloadNames, StringComparer.OrdinalIgnoreCase); 266 return new HashSet<string>(payloadNames, StringComparer.OrdinalIgnoreCase);
208 } 267 }
209 268
210 private ISet<string> GetMsiPropertyNames(string packageId) 269 private ISet<string> GetMsiPropertyNames()
211 { 270 {
212 var properties = this.Section.Symbols.OfType<WixBundleMsiPropertySymbol>() 271 var properties = this.Section.Symbols.OfType<WixBundleMsiPropertySymbol>()
213 .Where(p => p.PackageRef == packageId) 272 .Where(p => p.PackageRef == this.PackageId)
214 .Select(p => p.Name); 273 .Select(p => p.Name);
215 274
216 return new HashSet<string>(properties, StringComparer.Ordinal); 275 return new HashSet<string>(properties, StringComparer.Ordinal);
217 } 276 }
218 277
219 // https://docs.microsoft.com/en-us/windows/win32/msi/template-summary 278 // https://docs.microsoft.com/en-us/windows/win32/msi/template-summary
220 private bool IsWin64(SourceLineNumber sourceLineNumbers, string sourcePath, string platformsAndLanguages) 279 private bool IsWin64(string sourcePath, string platformsAndLanguages)
221 { 280 {
222 var separatorIndex = platformsAndLanguages.IndexOf(';'); 281 var separatorIndex = platformsAndLanguages.IndexOf(';');
223 var platformValue = separatorIndex > 0 ? platformsAndLanguages.Substring(0, separatorIndex) : platformsAndLanguages; 282 var platformValue = separatorIndex > 0 ? platformsAndLanguages.Substring(0, separatorIndex) : platformsAndLanguages;
@@ -234,27 +293,27 @@ namespace WixToolset.Core.Burn.Bundles
234 return false; 293 return false;
235 294
236 default: 295 default:
237 this.Messaging.Write(BurnBackendWarnings.UnknownMsiPackagePlatform(sourceLineNumbers, sourcePath, platformValue)); 296 this.Messaging.Write(BurnBackendWarnings.UnknownMsiPackagePlatform(this.PackagePayload.SourceLineNumbers, sourcePath, platformValue));
238 return true; 297 return true;
239 } 298 }
240 } 299 }
241 300
242 private void SetPerMachineAppropriately(string allusers, WixBundleMsiPackageSymbol msiPackage, string sourcePath) 301 private void SetPerMachineAppropriately(string allusers)
243 { 302 {
244 Debug.Assert(this.Facade.PackageSymbol.PerMachine.HasValue); 303 Debug.Assert(this.ChainPackage.PerMachine.HasValue);
245 var perMachine = this.Facade.PackageSymbol.PerMachine.Value; 304 var perMachine = this.ChainPackage.PerMachine.Value;
246 305
247 // Can ignore ALLUSERS from MsiProperties because it is not allowed there. 306 // Can ignore ALLUSERS from MsiProperties because it is not allowed there.
248 if (msiPackage.ForcePerMachine) 307 if (this.MsiPackage.ForcePerMachine)
249 { 308 {
250 if (!perMachine) 309 if (!perMachine)
251 { 310 {
252 this.Messaging.Write(WarningMessages.PerUserButForcingPerMachine(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath)); 311 this.Messaging.Write(WarningMessages.PerUserButForcingPerMachine(this.PackagePayload.SourceLineNumbers, this.PackageId));
253 this.Facade.PackageSymbol.PerMachine = true; // ensure that we think the package is per-machine. 312 this.ChainPackage.PerMachine = true; // ensure that we think the package is per-machine.
254 } 313 }
255 314
256 // Force ALLUSERS=1 via the MSI command-line. 315 // Force ALLUSERS=1 via the MSI command-line.
257 this.AddMsiProperty(msiPackage, "ALLUSERS", "1"); 316 this.AddMsiProperty("ALLUSERS", "1");
258 } 317 }
259 else 318 else
260 { 319 {
@@ -263,40 +322,40 @@ namespace WixToolset.Core.Burn.Bundles
263 // Not forced per-machine and no ALLUSERS property, flip back to per-user. 322 // Not forced per-machine and no ALLUSERS property, flip back to per-user.
264 if (perMachine) 323 if (perMachine)
265 { 324 {
266 this.Messaging.Write(WarningMessages.ImplicitlyPerUser(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath)); 325 this.Messaging.Write(WarningMessages.ImplicitlyPerUser(this.ChainPackage.SourceLineNumbers, this.PackageId));
267 this.Facade.PackageSymbol.PerMachine = false; 326 this.ChainPackage.PerMachine = false;
268 } 327 }
269 } 328 }
270 else if (allusers.Equals("1", StringComparison.Ordinal)) 329 else if (allusers.Equals("1", StringComparison.Ordinal))
271 { 330 {
272 if (!perMachine) 331 if (!perMachine)
273 { 332 {
274 this.Messaging.Write(ErrorMessages.PerUserButAllUsersEquals1(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath)); 333 this.Messaging.Write(ErrorMessages.PerUserButAllUsersEquals1(this.ChainPackage.SourceLineNumbers, this.PackageId));
275 } 334 }
276 } 335 }
277 else if (allusers.Equals("2", StringComparison.Ordinal)) 336 else if (allusers.Equals("2", StringComparison.Ordinal))
278 { 337 {
279 this.Messaging.Write(WarningMessages.DiscouragedAllUsersValue(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath, perMachine ? "machine" : "user")); 338 this.Messaging.Write(WarningMessages.DiscouragedAllUsersValue(this.ChainPackage.SourceLineNumbers, this.PackageId, perMachine ? "machine" : "user"));
280 } 339 }
281 else 340 else
282 { 341 {
283 this.Messaging.Write(ErrorMessages.UnsupportedAllUsersValue(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath, allusers)); 342 this.Messaging.Write(ErrorMessages.UnsupportedAllUsersValue(this.ChainPackage.SourceLineNumbers, this.PackageId, allusers));
284 } 343 }
285 } 344 }
286 } 345 }
287 346
288 private void SetPackageVisibility(string systemComponent, WixBundleMsiPackageSymbol msiPackage, ISet<string> msiPropertyNames) 347 private void SetPackageVisibility(string systemComponent, ISet<string> msiPropertyNames)
289 { 348 {
290 // If the authoring specifically added "ARPSYSTEMCOMPONENT", don't do it again. 349 // If the authoring specifically added "ARPSYSTEMCOMPONENT", don't do it again.
291 if (!msiPropertyNames.Contains("ARPSYSTEMCOMPONENT")) 350 if (!msiPropertyNames.Contains("ARPSYSTEMCOMPONENT"))
292 { 351 {
293 var alreadyVisible = String.IsNullOrEmpty(systemComponent); 352 var alreadyVisible = String.IsNullOrEmpty(systemComponent);
294 var visible = this.Facade.PackageSymbol.Visible; 353 var visible = this.ChainPackage.Visible;
295 354
296 // If not already set to the correct visibility. 355 // If not already set to the correct visibility.
297 if (alreadyVisible != visible) 356 if (alreadyVisible != visible)
298 { 357 {
299 this.AddMsiProperty(msiPackage, "ARPSYSTEMCOMPONENT", visible ? String.Empty : "1"); 358 this.AddMsiProperty("ARPSYSTEMCOMPONENT", visible ? String.Empty : "1");
300 } 359 }
301 } 360 }
302 } 361 }
@@ -318,9 +377,9 @@ namespace WixToolset.Core.Burn.Bundles
318 attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive ? WixBundleRelatedPackageAttributes.MaxInclusive : 0; 377 attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive ? WixBundleRelatedPackageAttributes.MaxInclusive : 0;
319 attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive ? 0 : WixBundleRelatedPackageAttributes.LangInclusive; 378 attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive ? 0 : WixBundleRelatedPackageAttributes.LangInclusive;
320 379
321 this.Section.AddSymbol(new WixBundleRelatedPackageSymbol(this.Facade.PackageSymbol.SourceLineNumbers) 380 this.Section.AddSymbol(new WixBundleRelatedPackageSymbol(this.PackagePayload.SourceLineNumbers)
322 { 381 {
323 PackageRef = this.Facade.PackageId, 382 PackageRef = this.PackageId,
324 RelatedId = record.GetString(1), 383 RelatedId = record.GetString(1),
325 MinVersion = record.GetString(2), 384 MinVersion = record.GetString(2),
326 MaxVersion = record.GetString(3), 385 MaxVersion = record.GetString(3),
@@ -366,9 +425,9 @@ namespace WixToolset.Core.Burn.Bundles
366 } 425 }
367 } 426 }
368 427
369 this.Section.AddSymbol(new WixBundleMsiFeatureSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, this.Facade.PackageId, featureName)) 428 this.Section.AddSymbol(new WixBundleMsiFeatureSymbol(this.PackagePayload.SourceLineNumbers, new Identifier(AccessModifier.Section, this.PackageId, featureName))
370 { 429 {
371 PackageRef = this.Facade.PackageId, 430 PackageRef = this.PackageId,
372 Name = featureName, 431 Name = featureName,
373 Parent = allFeaturesResultRecord.GetString(2), 432 Parent = allFeaturesResultRecord.GetString(2),
374 Title = allFeaturesResultRecord.GetString(3), 433 Title = allFeaturesResultRecord.GetString(3),
@@ -385,12 +444,14 @@ namespace WixToolset.Core.Burn.Bundles
385 } 444 }
386 } 445 }
387 446
388 private void ImportExternalCabinetAsPayloads(Database db, WixBundlePayloadSymbol packagePayload, ISet<string> payloadNames) 447 private void ImportExternalCabinetAsPayloads(Database db, ISet<string> payloadNames)
389 { 448 {
390 if (db.TableExists("Media")) 449 if (db.TableExists("Media"))
391 { 450 {
392 using (var view = db.OpenExecuteView("SELECT `Cabinet` FROM `Media`")) 451 using (var view = db.OpenExecuteView("SELECT `Cabinet` FROM `Media`"))
393 { 452 {
453 var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
454
394 foreach (var cabinetRecord in view.Records) 455 foreach (var cabinetRecord in view.Records)
395 { 456 {
396 var cabinet = cabinetRecord.GetString(1); 457 var cabinet = cabinetRecord.GetString(1);
@@ -400,34 +461,34 @@ namespace WixToolset.Core.Burn.Bundles
400 // If we didn't find the Payload as an existing child of the package, we need to 461 // If we didn't find the Payload as an existing child of the package, we need to
401 // add it. We expect the file to exist on-disk in the same relative location as 462 // add it. We expect the file to exist on-disk in the same relative location as
402 // the MSI expects to find it... 463 // the MSI expects to find it...
403 var cabinetName = Path.Combine(Path.GetDirectoryName(packagePayload.Name), cabinet); 464 var cabinetName = Path.Combine(Path.GetDirectoryName(this.PackagePayload.Name), cabinet);
404 465
405 if (!payloadNames.Contains(cabinetName)) 466 if (!payloadNames.Contains(cabinetName))
406 { 467 {
407 var generatedId = this.BackendHelper.GenerateIdentifier("cab", packagePayload.Id.Id, cabinet); 468 var generatedId = this.BackendHelper.GenerateIdentifier("cab", this.PackagePayload.Id.Id, cabinet);
408 var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.Facade.PackageSymbol.SourceLineNumbers); 469 var payloadSourceFile = this.ResolveRelatedFile(this.PackagePayload.SourceFile.Path, this.PackagePayload.UnresolvedSourceFile, cabinet, "Cabinet", sourceLineNumbers);
409 470
410 this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers) 471 this.Section.AddSymbol(new WixGroupSymbol(sourceLineNumbers)
411 { 472 {
412 ParentType = ComplexReferenceParentType.Package, 473 ParentType = ComplexReferenceParentType.Package,
413 ParentId = this.Facade.PackageId, 474 ParentId = this.PackageId,
414 ChildType = ComplexReferenceChildType.Payload, 475 ChildType = ComplexReferenceChildType.Payload,
415 ChildId = generatedId 476 ChildId = generatedId
416 }); 477 });
417 478
418 this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) 479 this.Section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, generatedId))
419 { 480 {
420 Name = cabinetName, 481 Name = cabinetName,
421 SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile }, 482 SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile },
422 Compressed = packagePayload.Compressed, 483 Compressed = this.PackagePayload.Compressed,
423 UnresolvedSourceFile = cabinetName, 484 UnresolvedSourceFile = cabinetName,
424 ContainerRef = packagePayload.ContainerRef, 485 ContainerRef = this.PackagePayload.ContainerRef,
425 DownloadUrl = packagePayload.DownloadUrl, 486 DownloadUrl = this.PackagePayload.DownloadUrl,
426 Packaging = packagePayload.Packaging, 487 Packaging = this.PackagePayload.Packaging,
427 ParentPackagePayloadRef = packagePayload.Id.Id, 488 ParentPackagePayloadRef = this.PackagePayload.Id.Id,
428 }); 489 });
429 490
430 this.CheckIfWindowsInstallerFileTooLarge(this.Facade.PackageSymbol.SourceLineNumbers, payloadSourceFile, "cabinet"); 491 this.CheckIfWindowsInstallerFileTooLarge(sourceLineNumbers, payloadSourceFile, "cabinet");
431 } 492 }
432 } 493 }
433 } 494 }
@@ -435,7 +496,7 @@ namespace WixToolset.Core.Burn.Bundles
435 } 496 }
436 } 497 }
437 498
438 private long ImportExternalFileAsPayloadsAndReturnInstallSize(Database db, WixBundlePayloadSymbol packagePayload, bool longNamesInImage, bool compressed, ISet<string> payloadNames) 499 private long ImportExternalFileAsPayloadsAndReturnInstallSize(Database db, bool longNamesInImage, bool compressed, ISet<string> payloadNames)
439 { 500 {
440 long size = 0; 501 long size = 0;
441 502
@@ -461,6 +522,8 @@ namespace WixToolset.Core.Burn.Bundles
461 // install size of the package. 522 // install size of the package.
462 using (var view = db.OpenExecuteView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`")) 523 using (var view = db.OpenExecuteView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`"))
463 { 524 {
525 var sourceLineNumbers = this.PackagePayload.SourceLineNumbers;
526
464 foreach (var record in view.Records) 527 foreach (var record in view.Records)
465 { 528 {
466 // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not 529 // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not
@@ -470,31 +533,31 @@ namespace WixToolset.Core.Burn.Bundles
470 (!compressed && 0 == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesCompressed))) 533 (!compressed && 0 == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesCompressed)))
471 { 534 {
472 var fileSourcePath = this.PathResolver.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage); 535 var fileSourcePath = this.PathResolver.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage);
473 var name = Path.Combine(Path.GetDirectoryName(packagePayload.Name), fileSourcePath); 536 var name = Path.Combine(Path.GetDirectoryName(this.PackagePayload.Name), fileSourcePath);
474 537
475 if (!payloadNames.Contains(name)) 538 if (!payloadNames.Contains(name))
476 { 539 {
477 var generatedId = this.BackendHelper.GenerateIdentifier("f", packagePayload.Id.Id, record.GetString(2)); 540 var generatedId = this.BackendHelper.GenerateIdentifier("f", this.PackagePayload.Id.Id, record.GetString(2));
478 var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.Facade.PackageSymbol.SourceLineNumbers); 541 var payloadSourceFile = this.ResolveRelatedFile(this.PackagePayload.SourceFile.Path, this.PackagePayload.UnresolvedSourceFile, fileSourcePath, "File", sourceLineNumbers);
479 542
480 this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers) 543 this.Section.AddSymbol(new WixGroupSymbol(sourceLineNumbers)
481 { 544 {
482 ParentType = ComplexReferenceParentType.Package, 545 ParentType = ComplexReferenceParentType.Package,
483 ParentId = this.Facade.PackageId, 546 ParentId = this.PackageId,
484 ChildType = ComplexReferenceChildType.Payload, 547 ChildType = ComplexReferenceChildType.Payload,
485 ChildId = generatedId 548 ChildId = generatedId
486 }); 549 });
487 550
488 this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) 551 this.Section.AddSymbol(new WixBundlePayloadSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, generatedId))
489 { 552 {
490 Name = name, 553 Name = name,
491 SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile }, 554 SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile },
492 Compressed = packagePayload.Compressed, 555 Compressed = this.PackagePayload.Compressed,
493 UnresolvedSourceFile = name, 556 UnresolvedSourceFile = name,
494 ContainerRef = packagePayload.ContainerRef, 557 ContainerRef = this.PackagePayload.ContainerRef,
495 DownloadUrl = packagePayload.DownloadUrl, 558 DownloadUrl = this.PackagePayload.DownloadUrl,
496 Packaging = packagePayload.Packaging, 559 Packaging = this.PackagePayload.Packaging,
497 ParentPackagePayloadRef = packagePayload.Id.Id, 560 ParentPackagePayloadRef = this.PackagePayload.Id.Id,
498 }); 561 });
499 } 562 }
500 } 563 }
@@ -507,23 +570,23 @@ namespace WixToolset.Core.Burn.Bundles
507 return size; 570 return size;
508 } 571 }
509 572
510 private void AddMsiProperty(WixBundleMsiPackageSymbol msiPackage, string name, string value) 573 private void AddMsiProperty(string name, string value)
511 { 574 {
512 this.Section.AddSymbol(new WixBundleMsiPropertySymbol(msiPackage.SourceLineNumbers, new Identifier(AccessModifier.Section, msiPackage.Id.Id, name)) 575 this.Section.AddSymbol(new WixBundleMsiPropertySymbol(this.PackagePayload.SourceLineNumbers, new Identifier(AccessModifier.Section, this.PackageId, name))
513 { 576 {
514 PackageRef = msiPackage.Id.Id, 577 PackageRef = this.PackageId,
515 Name = name, 578 Name = name,
516 Value = value, 579 Value = value,
517 }); 580 });
518 } 581 }
519 582
520 private void ImportDependencyProviders(Database db, WixBundleMsiPackageSymbol msiPackage) 583 private void ImportDependencyProviders(Database db)
521 { 584 {
522 this.ImportDependencyProvidersFromTable(db, msiPackage, "WixDependencyProvider"); 585 this.ImportDependencyProvidersFromTable(db, "WixDependencyProvider");
523 this.ImportDependencyProvidersFromTable(db, msiPackage, "Wix4DependencyProvider"); 586 this.ImportDependencyProvidersFromTable(db, "Wix4DependencyProvider");
524 } 587 }
525 588
526 private void ImportDependencyProvidersFromTable(Database db, WixBundleMsiPackageSymbol msiPackage, string tableName) 589 private void ImportDependencyProvidersFromTable(Database db, string tableName)
527 { 590 {
528 if (db.TableExists(tableName)) 591 if (db.TableExists(tableName))
529 { 592 {
@@ -531,15 +594,15 @@ namespace WixToolset.Core.Burn.Bundles
531 { 594 {
532 foreach (var record in view.Records) 595 foreach (var record in view.Records)
533 { 596 {
534 var id = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", msiPackage.Id.Id, record.GetString(1))); 597 var id = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", this.PackageId, record.GetString(1)));
535 598
536 // Import the provider key and attributes. 599 // Import the provider key and attributes.
537 this.Section.AddSymbol(new WixDependencyProviderSymbol(msiPackage.SourceLineNumbers, id) 600 this.Section.AddSymbol(new WixDependencyProviderSymbol(this.PackagePayload.SourceLineNumbers, id)
538 { 601 {
539 ParentRef = msiPackage.Id.Id, 602 ParentRef = this.PackageId,
540 ProviderKey = record.GetString(2), 603 ProviderKey = record.GetString(2),
541 Version = record.GetString(3) ?? msiPackage.ProductVersion, 604 Version = record.GetString(3) ?? this.MsiPackage.ProductVersion,
542 DisplayName = record.GetString(4) ?? this.Facade.PackageSymbol.DisplayName, 605 DisplayName = record.GetString(4) ?? this.ChainPackage.DisplayName,
543 Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported | (WixDependencyProviderAttributes)record.GetInteger(5), 606 Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported | (WixDependencyProviderAttributes)record.GetInteger(5),
544 }); 607 });
545 } 608 }
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs
index d306957e..cef68c8a 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs
@@ -5,6 +5,7 @@ namespace WixToolset.Core.Burn.Bundles
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.IO; 7 using System.IO;
8 using System.Linq;
8 using System.Text; 9 using System.Text;
9 using System.Xml; 10 using System.Xml;
10 using WixToolset.Core.Native.Msi; 11 using WixToolset.Core.Native.Msi;
@@ -29,30 +30,71 @@ namespace WixToolset.Core.Burn.Bundles
29 public ProcessMspPackageCommand(IMessaging messaging, IntermediateSection section, PackageFacade facade, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols) 30 public ProcessMspPackageCommand(IMessaging messaging, IntermediateSection section, PackageFacade facade, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols)
30 { 31 {
31 this.Messaging = messaging; 32 this.Messaging = messaging;
32
33 this.AuthoredPayloads = payloadSymbols;
34 this.Section = section; 33 this.Section = section;
35 this.Facade = facade; 34
35 this.ChainPackage = facade.PackageSymbol;
36 this.MspPackage = (WixBundleMspPackageSymbol)facade.SpecificPackageSymbol;
37 this.PackagePayload = payloadSymbols[this.ChainPackage.PayloadRef];
36 } 38 }
37 39
38 public IMessaging Messaging { get; } 40 private IMessaging Messaging { get; }
39 41
40 public Dictionary<string, WixBundlePayloadSymbol> AuthoredPayloads { private get; set; } 42 private WixBundlePackageSymbol ChainPackage { get; }
41 43
42 public PackageFacade Facade { private get; set; } 44 private WixBundleMspPackageSymbol MspPackage { get; }
43 45
44 public IntermediateSection Section { get; } 46 private WixBundlePayloadSymbol PackagePayload { get; }
47
48 private IntermediateSection Section { get; }
45 49
46 /// <summary> 50 /// <summary>
47 /// Processes the Msp packages to add properties and payloads from the Msp packages. 51 /// Processes the Msp packages to add properties and payloads from the Msp packages.
48 /// </summary> 52 /// </summary>
49 public void Execute() 53 public void Execute()
50 { 54 {
51 var packagePayload = this.AuthoredPayloads[this.Facade.PackageSymbol.PayloadRef]; 55 var harvestedMspPackage = this.Section.Symbols.OfType<WixBundleHarvestedMspPackageSymbol>()
56 .Where(h => h.Id == this.ChainPackage.Id)
57 .SingleOrDefault();
58
59 if (harvestedMspPackage == null)
60 {
61 harvestedMspPackage = this.HarvestPackage();
62
63 if (harvestedMspPackage == null)
64 {
65 return;
66 }
67 }
68
69 this.MspPackage.PatchCode = harvestedMspPackage.PatchCode;
70 this.MspPackage.Manufacturer = harvestedMspPackage.ManufacturerName;
71 this.MspPackage.PatchXml = harvestedMspPackage.PatchXml;
72
73 if (String.IsNullOrEmpty(this.ChainPackage.DisplayName))
74 {
75 this.ChainPackage.DisplayName = harvestedMspPackage.DisplayName;
76 }
52 77
53 var mspPackage = (WixBundleMspPackageSymbol)this.Facade.SpecificPackageSymbol; 78 if (String.IsNullOrEmpty(this.ChainPackage.Description))
79 {
80 this.ChainPackage.Description = harvestedMspPackage.Description;
81 }
54 82
55 var sourcePath = packagePayload.SourceFile.Path; 83 if (String.IsNullOrEmpty(this.ChainPackage.CacheId))
84 {
85 this.ChainPackage.CacheId = this.MspPackage.PatchCode;
86 }
87 }
88
89 private WixBundleHarvestedMspPackageSymbol HarvestPackage()
90 {
91 string patchCode;
92 string displayName;
93 string description;
94 string manufacturerName;
95 string patchXml;
96
97 var sourcePath = this.PackagePayload.SourceFile.Path;
56 98
57 try 99 try
58 { 100 {
@@ -61,41 +103,37 @@ namespace WixToolset.Core.Burn.Bundles
61 // Read data out of the msp database... 103 // Read data out of the msp database...
62 using (var sumInfo = new SummaryInformation(db)) 104 using (var sumInfo = new SummaryInformation(db))
63 { 105 {
64 var patchCode = sumInfo.GetProperty(SummaryInformation.Patch.PatchCode); 106 var patchCodeValue = sumInfo.GetProperty(SummaryInformation.Patch.PatchCode);
65 mspPackage.PatchCode = patchCode.Substring(0, 38); 107 patchCode = patchCodeValue.Substring(0, 38);
66 } 108 }
67 109
68 using (var view = db.OpenView(PatchMetadataQuery)) 110 using (var view = db.OpenView(PatchMetadataQuery))
69 { 111 {
70 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) 112 displayName = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "DisplayName");
71 { 113 description = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "Description");
72 this.Facade.PackageSymbol.DisplayName = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "DisplayName"); 114 manufacturerName = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "ManufacturerName");
73 }
74
75 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Description))
76 {
77 this.Facade.PackageSymbol.Description = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "Description");
78 }
79
80 mspPackage.Manufacturer = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "ManufacturerName");
81 } 115 }
82 } 116 }
83 117
84 this.ProcessPatchXml(packagePayload, mspPackage, sourcePath); 118 patchXml = ProcessMspPackageCommand.ProcessPatchXml(sourcePath, this.Section, this.PackagePayload.SourceLineNumbers, this.PackagePayload.Id);
85 } 119 }
86 catch (MsiException e) 120 catch (MsiException e)
87 { 121 {
88 this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(packagePayload.SourceLineNumbers, sourcePath, e.Message)); 122 this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(this.PackagePayload.SourceLineNumbers, sourcePath, e.Message));
89 return; 123 return null;
90 } 124 }
91 125
92 if (String.IsNullOrEmpty(this.Facade.PackageSymbol.CacheId)) 126 return this.Section.AddSymbol(new WixBundleHarvestedMspPackageSymbol(this.PackagePayload.SourceLineNumbers, this.ChainPackage.Id)
93 { 127 {
94 this.Facade.PackageSymbol.CacheId = mspPackage.PatchCode; 128 PatchCode = patchCode,
95 } 129 DisplayName = displayName,
130 Description = description,
131 ManufacturerName = manufacturerName,
132 PatchXml = patchXml,
133 });
96 } 134 }
97 135
98 private void ProcessPatchXml(WixBundlePayloadSymbol packagePayload, WixBundleMspPackageSymbol mspPackage, string sourcePath) 136 private static string ProcessPatchXml(string sourcePath, IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id)
99 { 137 {
100 var uniqueTargetCodes = new Dictionary<string, WixBundlePatchTargetCodeSymbol>(); 138 var uniqueTargetCodes = new Dictionary<string, WixBundlePatchTargetCodeSymbol>();
101 139
@@ -135,9 +173,9 @@ namespace WixToolset.Core.Burn.Bundles
135 173
136 if (!uniqueTargetCodes.TryGetValue(targetCode, out var existing)) 174 if (!uniqueTargetCodes.TryGetValue(targetCode, out var existing))
137 { 175 {
138 var symbol = this.Section.AddSymbol(new WixBundlePatchTargetCodeSymbol(packagePayload.SourceLineNumbers) 176 var symbol = section.AddSymbol(new WixBundlePatchTargetCodeSymbol(sourceLineNumbers)
139 { 177 {
140 PackageRef = packagePayload.Id.Id, 178 PackageRef = id.Id,
141 TargetCode = targetCode, 179 TargetCode = targetCode,
142 Attributes = 0, 180 Attributes = 0,
143 Type = type, 181 Type = type,
@@ -158,6 +196,8 @@ namespace WixToolset.Core.Burn.Bundles
158 root.RemoveChild(node); 196 root.RemoveChild(node);
159 } 197 }
160 198
199 string compactPatchXml;
200
161 // Save the XML as compact as possible. 201 // Save the XML as compact as possible.
162 using (var writer = new StringWriter()) 202 using (var writer = new StringWriter())
163 { 203 {
@@ -166,8 +206,10 @@ namespace WixToolset.Core.Burn.Bundles
166 doc.WriteTo(xmlWriter); 206 doc.WriteTo(xmlWriter);
167 } 207 }
168 208
169 mspPackage.PatchXml = writer.ToString(); 209 compactPatchXml = writer.ToString();
170 } 210 }
211
212 return compactPatchXml;
171 } 213 }
172 214
173 private static string GetPatchMetadataProperty(View view, string property) 215 private static string GetPatchMetadataProperty(View view, string property)
diff --git a/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs b/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs
index 7235c792..0c305331 100644
--- a/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs
+++ b/src/wix/WixToolset.Core.Burn/BurnBackendWarnings.cs
@@ -26,9 +26,9 @@ namespace WixToolset.Core.Burn
26 return Message(sourceLineNumbers, Ids.FailedToExtractAttachedContainers, "Failed to extract attached container. This most often happens when extracting a stripped bundle from the package cache, which is not supported."); 26 return Message(sourceLineNumbers, Ids.FailedToExtractAttachedContainers, "Failed to extract attached container. This most often happens when extracting a stripped bundle from the package cache, which is not supported.");
27 } 27 }
28 28
29 public static Message HiddenBundleNotSupported(SourceLineNumber sourceLineNumbers, string bundleExecutable) 29 public static Message HiddenBundleNotSupported(SourceLineNumber sourceLineNumbers, string packageId)
30 { 30 {
31 return Message(sourceLineNumbers, Ids.HiddenBundleNotSupported, "The bundle '{0}' does not support hiding its ARP registration.", bundleExecutable); 31 return Message(sourceLineNumbers, Ids.HiddenBundleNotSupported, "The BundlePackage '{0}' does not support hiding its ARP registration.", packageId);
32 } 32 }
33 33
34 public static Message UnknownBundleRelationAction(SourceLineNumber sourceLineNumbers, string bundleExecutable, string action) 34 public static Message UnknownBundleRelationAction(SourceLineNumber sourceLineNumbers, string bundleExecutable, string action)
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
index 7cd13ebf..2925abb1 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs
@@ -238,7 +238,7 @@ namespace WixToolsetTest.CoreIntegration
238 .ToArray(); 238 .ToArray();
239 WixAssert.CompareLineByLine(new[] 239 WixAssert.CompareLineByLine(new[]
240 { 240 {
241 "The bundle '<dotDataPath>\\v3bundle.exe' does not support hiding its ARP registration.", 241 "The BundlePackage 'v3bundle.exe' does not support hiding its ARP registration.",
242 }, warningMessages); 242 }, warningMessages);
243 243
244 Assert.True(File.Exists(parentBundlePath)); 244 Assert.True(File.Exists(parentBundlePath));