aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2019-05-22 00:54:09 -0700
committerRob Mensching <rob@firegiant.com>2019-05-23 16:07:04 -0700
commitb645ddc2c1386c1199ca1e7790201d7a5ab6627b (patch)
treea814a22337e2350b8ae26d74d806af4da2ed4e0f /src/test
parent6f6c485118796f044a278447722eaf18ac5bf86e (diff)
downloadwix-b645ddc2c1386c1199ca1e7790201d7a5ab6627b.tar.gz
wix-b645ddc2c1386c1199ca1e7790201d7a5ab6627b.tar.bz2
wix-b645ddc2c1386c1199ca1e7790201d7a5ab6627b.zip
Integrate latest changes to tuple definitions
Diffstat (limited to 'src/test')
-rw-r--r--src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs747
1 files changed, 455 insertions, 292 deletions
diff --git a/src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs b/src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs
index ae33d6b1..9b1fa4cf 100644
--- a/src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs
+++ b/src/test/WixToolsetTest.Converters.Tupleizer/ConvertTuplesFixture.cs
@@ -3,6 +3,7 @@
3namespace WixToolsetTest.Converters.Tupleizer 3namespace WixToolsetTest.Converters.Tupleizer
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic;
6 using System.IO; 7 using System.IO;
7 using System.Linq; 8 using System.Linq;
8 using WixBuildTools.TestSupport; 9 using WixBuildTools.TestSupport;
@@ -42,350 +43,512 @@ namespace WixToolsetTest.Converters.Tupleizer
42 43
43 intermediate = Intermediate.Load(wixiplFile); 44 intermediate = Intermediate.Load(wixiplFile);
44 45
46 var wixMediaByDiskId = IndexWixMediaTableByDiskId(output);
47
45 // Dump to text for easy diffing, with some massaging to keep v3 and v4 diffable. 48 // Dump to text for easy diffing, with some massaging to keep v3 and v4 diffable.
46 // 49 //
47 var tables = output.Tables.Cast<Wix3.Table>(); 50 var tables = output.Tables.Cast<Wix3.Table>();
48 var wix3Dump = tables 51 var wix3Dump = tables
49 .SelectMany(table => table.Rows.Cast<Wix3.Row>() 52 .SelectMany(table => table.Rows.Cast<Wix3.Row>()
50 .Select(row => RowToString(row))) 53 .SelectMany(row => RowToStrings(row, wixMediaByDiskId)))
54 .Where(s => !String.IsNullOrEmpty(s))
55 .OrderBy(s => s)
51 .ToArray(); 56 .ToArray();
52 57
53 var tuples = intermediate.Sections.SelectMany(s => s.Tuples); 58 var tuples = intermediate.Sections.SelectMany(s => s.Tuples);
54 var wix4Dump = tuples.Select(tuple => TupleToString(tuple)).ToArray(); 59 var wix4Dump = tuples
60 .SelectMany(tuple => TupleToStrings(tuple))
61 .OrderBy(s => s)
62 .ToArray();
55 63
64#if false
56 Assert.Equal(wix3Dump, wix4Dump); 65 Assert.Equal(wix3Dump, wix4Dump);
66#else // useful when you want to diff the outputs with another diff tool.
67 var wix3TextDump = String.Join(Environment.NewLine, wix3Dump);
68 var wix4TextDump = String.Join(Environment.NewLine, wix4Dump);
57 69
58 // Useful when you want to diff the outputs with another diff tool... 70 File.WriteAllText(Path.Combine(Path.GetTempPath(), "~3.txt"), wix3TextDump);
59 // 71 File.WriteAllText(Path.Combine(Path.GetTempPath(), "~4.txt"), wix4TextDump);
60 //var wix3TextDump = String.Join(Environment.NewLine, wix3Dump.OrderBy(val => val)); 72
61 //var wix4TextDump = String.Join(Environment.NewLine, wix4Dump.OrderBy(val => val)); 73 Assert.Equal(wix3TextDump, wix4TextDump);
62 //Assert.Equal(wix3TextDump, wix4TextDump); 74#endif
63 } 75 }
64 } 76 }
65 77
66 private static string RowToString(Wix3.Row row) 78 private static Dictionary<int, Wix3.WixMediaRow> IndexWixMediaTableByDiskId(Wix3.Output output)
67 { 79 {
68 var fields = String.Join(",", row.Fields.Select(field => field.Data?.ToString())); 80 var wixMediaByDiskId = new Dictionary<int, Wix3.WixMediaRow>();
81 var wixMediaTable = output.Tables["WixMedia"];
69 82
70 // Massage output to match WiX v3 rows and v4 tuples. 83 if (wixMediaTable != null)
71 //
72 switch (row.Table.Name)
73 { 84 {
74 case "File": 85 foreach (Wix3.WixMediaRow row in wixMediaTable.Rows)
75 var fieldValues = row.Fields.Take(7).Select(field => field.Data?.ToString()).ToArray(); 86 {
76 if (fieldValues[3] == null) 87 wixMediaByDiskId.Add((int)row[0], row);
77 { 88 }
78 // "Somebody" sometimes writes out a null field even when the column definition says
79 // it's non-nullable. Not naming names or anything. (SWID tags.)
80 fieldValues[3] = "0";
81 }
82 fields = String.Join(",", fieldValues);
83 break;
84 case "WixFile":
85 fields = String.Join(",", row.Fields.Take(8).Select(field => field.Data?.ToString()));
86 break;
87 } 89 }
88 90
89 return $"{row.Table.Name},{fields}"; 91 return wixMediaByDiskId;
90 } 92 }
91 93
92 private static string TupleToString(WixToolset.Data.IntermediateTuple tuple) 94 private static IEnumerable<string> RowToStrings(Wix3.Row row, Dictionary<int, Wix3.WixMediaRow> wixMediaByDiskId)
93 { 95 {
94 var fields = String.Join(",", tuple.Fields.Select(field => field?.AsString())); 96 string fields = null;
95 97
96 switch (tuple.Definition.Name) 98 // Massage output to match WiX v3 rows and v4 tuples.
99 //
100 switch (row.Table.Name)
97 { 101 {
98 // Massage output to match WiX v3 rows and v4 tuples. 102 case "Directory":
99 // 103 var dirs = SplitDefaultDir((string)row[2]);
100 case "Component": 104 fields = String.Join(",", row[0], row[1], dirs[0], dirs[1], dirs[2], dirs[3]);
101 { 105 break;
102 var componentTuple = (ComponentTuple)tuple; 106 case "File":
103 var attributes = ComponentLocation.Either == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0; 107 {
104 attributes |= ComponentLocation.SourceOnly == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0; 108 var fieldValues = row.Fields.Take(7).Select(SafeConvertField).ToArray();
105 attributes |= ComponentKeyPathType.Registry == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0; 109 if (fieldValues[3] == null)
106 attributes |= ComponentKeyPathType.OdbcDataSource == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0;
107 attributes |= componentTuple.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0;
108 attributes |= componentTuple.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0;
109 attributes |= componentTuple.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0;
110 attributes |= componentTuple.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0;
111 attributes |= componentTuple.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0;
112 attributes |= componentTuple.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0;
113 attributes |= componentTuple.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
114 attributes |= componentTuple.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
115
116 fields = String.Join(",",
117 componentTuple.ComponentId,
118 componentTuple.Directory_,
119 attributes.ToString(),
120 componentTuple.Condition,
121 componentTuple.KeyPath
122 );
123 break;
124 }
125 case "CustomAction":
126 { 110 {
127 var customActionTuple = (CustomActionTuple)tuple; 111 // "Somebody" sometimes writes out a null field even when the column definition says
128 var type = customActionTuple.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0; 112 // it's non-nullable. Not naming names or anything. (SWID tags.)
129 type |= customActionTuple.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0; 113 fieldValues[3] = "0";
130 type |= customActionTuple.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate;
131 type |= customActionTuple.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0;
132 type |= customActionTuple.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0;
133 type |= customActionTuple.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0;
134 type |= CustomActionExecutionType.FirstSequence == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0;
135 type |= CustomActionExecutionType.OncePerProcess == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0;
136 type |= CustomActionExecutionType.ClientRepeat == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0;
137 type |= CustomActionExecutionType.Deferred == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0;
138 type |= CustomActionExecutionType.Rollback == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0;
139 type |= CustomActionExecutionType.Commit == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0;
140 type |= CustomActionSourceType.File == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0;
141 type |= CustomActionSourceType.Directory == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0;
142 type |= CustomActionSourceType.Property == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0;
143 type |= CustomActionTargetType.Dll == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0;
144 type |= CustomActionTargetType.Exe == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0;
145 type |= CustomActionTargetType.TextData == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0;
146 type |= CustomActionTargetType.JScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0;
147 type |= CustomActionTargetType.VBScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0;
148
149 fields = String.Join(",",
150 type.ToString(),
151 customActionTuple.Source,
152 customActionTuple.Target,
153 customActionTuple.PatchUninstall ? WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall.ToString() : null
154 );
155 break;
156 } 114 }
157 case "Feature": 115 fields = String.Join(",", fieldValues);
158 { 116 break;
159 var featureTuple = (FeatureTuple)tuple; 117 }
160 var attributes = featureTuple.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0; 118 case "Media":
161 attributes |= featureTuple.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0; 119 var compression = wixMediaByDiskId.TryGetValue((int)row[0], out var wixMedia) ? (CompressionLevel?)Enum.Parse(typeof(CompressionLevel), SafeConvertField(wixMedia.Fields[1]), true) : null;
162 attributes |= FeatureInstallDefault.FollowParent == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0; 120
163 attributes |= FeatureInstallDefault.Source == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0; 121 fields = String.Join(",", row.Fields.Select(SafeConvertField));
164 attributes |= FeatureTypicalDefault.Advertise == featureTuple.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0; 122 fields = String.Join(",", fields, (int?)compression, SafeConvertField(wixMedia?.Fields[2]));
165 123 break;
166 fields = String.Join(",", 124 case "RegLocator":
167 featureTuple.Feature_Parent, 125 var type = (int)row[4];
168 featureTuple.Title, 126 fields = String.Join(",", row[0], row[1], row[2], row[3], type & 0xF, (type & 0x10) == 0x10);
169 featureTuple.Description, 127 break;
170 featureTuple.Display.ToString(), 128 case "RemoveFile":
171 featureTuple.Level.ToString(), 129 var attributes = (int)row[4];
172 featureTuple.Directory_, 130 var onInstall = (attributes & 1) == 1 ? (bool?)true : null;
173 attributes.ToString()); 131 var onUninstall = (attributes & 2) == 2 ? (bool?)true : null;
174 break; 132 fields = String.Join(",", row.Fields.Take(4).Select(SafeConvertField));
175 } 133 fields = String.Join(",", fields, onInstall, onUninstall);
176 case "File": 134 break;
135 case "Shortcut":
136 var split = ((string)row[2]).Split('|');
137 var afterName = String.Join(",", row.Fields.Skip(3).Select(SafeConvertField));
138 fields = String.Join(",", row[0], row[1], split.Length > 1 ? split[1] : split[0], split.Length > 1 ? split[0] : String.Empty, afterName);
139 break;
140 case "WixAction":
141 var table = (int)SequenceStringToSequenceTable(row[0]);
142 fields = String.Join(",", table, row[1], row[2], row[3], row[4], row[5], row[6]);
143 break;
144 case "WixFile":
145 {
146 var fieldValues = row.Fields.Take(10).Select(SafeConvertField).ToArray();
147 if (fieldValues[8] == null)
177 { 148 {
178 var fileTuple = (FileTuple)tuple; 149 // "Somebody" sometimes writes out a null field even when the column definition says
179 fields = String.Join(",", 150 // it's non-nullable. Not naming names or anything. (SWID tags.)
180 fileTuple.Component_, 151 fieldValues[8] = "0";
181 fileTuple.LongFileName,
182 fileTuple.FileSize.ToString(),
183 fileTuple.Version,
184 fileTuple.Language,
185 ((fileTuple.ReadOnly ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0)
186 | (fileTuple.Hidden ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0)
187 | (fileTuple.System ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0)
188 | (fileTuple.Vital ? WindowsInstallerConstants.MsidbFileAttributesVital : 0)
189 | (fileTuple.Checksum ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0)
190 | ((fileTuple.Compressed.HasValue && fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0)
191 | ((fileTuple.Compressed.HasValue && !fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0))
192 .ToString());
193 break;
194 } 152 }
153 fields = String.Join(",", fieldValues);
154 break;
155 }
156 case "WixMedia":
157 break;
158 default:
159 fields = String.Join(",", row.Fields.Select(SafeConvertField));
160 break;
161 }
195 162
196 case "Registry": 163 if (fields != null)
197 { 164 {
198 var registryTuple = (RegistryTuple)tuple; 165 yield return $"{row.Table.Name}:{fields}";
199 var value = registryTuple.Value; 166 }
200 167 }
201 switch (registryTuple.ValueType)
202 {
203 case RegistryValueType.Binary:
204 value = String.Concat("#x", value);
205 break;
206 case RegistryValueType.Expandable:
207 value = String.Concat("#%", value);
208 break;
209 case RegistryValueType.Integer:
210 value = String.Concat("#", value);
211 break;
212 case RegistryValueType.MultiString:
213 switch (registryTuple.ValueAction)
214 {
215 case RegistryValueActionType.Append:
216 value = String.Concat("[~]", value);
217 break;
218 case RegistryValueActionType.Prepend:
219 value = String.Concat(value, "[~]");
220 break;
221 case RegistryValueActionType.Write:
222 default:
223 if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal))
224 {
225 value = String.Concat("[~]", value, "[~]");
226 }
227 break;
228 }
229 break;
230 case RegistryValueType.String:
231 // escape the leading '#' character for string registry keys
232 if (null != value && value.StartsWith("#", StringComparison.Ordinal))
233 {
234 value = String.Concat("#", value);
235 }
236 break;
237 }
238 168
239 fields = String.Join(",", 169 private static IEnumerable<string> TupleToStrings(IntermediateTuple tuple)
240 ((int)registryTuple.Root).ToString(), 170 {
241 registryTuple.Key, 171 string fields;
242 registryTuple.Name, 172 switch (tuple.Definition.Name)
243 value, 173 {
244 registryTuple.Component_ 174 // Massage output to match WiX v3 rows and v4 tuples.
245 ); 175 //
246 break; 176 case "Component":
247 } 177 {
178 var componentTuple = (ComponentTuple)tuple;
179 var attributes = ComponentLocation.Either == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesOptional : 0;
180 attributes |= ComponentLocation.SourceOnly == componentTuple.Location ? WindowsInstallerConstants.MsidbComponentAttributesSourceOnly : 0;
181 attributes |= ComponentKeyPathType.Registry == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesRegistryKeyPath : 0;
182 attributes |= ComponentKeyPathType.OdbcDataSource == componentTuple.KeyPathType ? WindowsInstallerConstants.MsidbComponentAttributesODBCDataSource : 0;
183 attributes |= componentTuple.DisableRegistryReflection ? WindowsInstallerConstants.MsidbComponentAttributesDisableRegistryReflection : 0;
184 attributes |= componentTuple.NeverOverwrite ? WindowsInstallerConstants.MsidbComponentAttributesNeverOverwrite : 0;
185 attributes |= componentTuple.Permanent ? WindowsInstallerConstants.MsidbComponentAttributesPermanent : 0;
186 attributes |= componentTuple.SharedDllRefCount ? WindowsInstallerConstants.MsidbComponentAttributesSharedDllRefCount : 0;
187 attributes |= componentTuple.Shared ? WindowsInstallerConstants.MsidbComponentAttributesShared : 0;
188 attributes |= componentTuple.Transitive ? WindowsInstallerConstants.MsidbComponentAttributesTransitive : 0;
189 attributes |= componentTuple.UninstallWhenSuperseded ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
190 attributes |= componentTuple.Win64 ? WindowsInstallerConstants.MsidbComponentAttributes64bit : 0;
191
192 fields = String.Join(",",
193 componentTuple.ComponentId,
194 componentTuple.DirectoryRef,
195 attributes.ToString(),
196 componentTuple.Condition,
197 componentTuple.KeyPath
198 );
199 break;
200 }
201 case "CustomAction":
202 {
203 var customActionTuple = (CustomActionTuple)tuple;
204 var type = customActionTuple.Win64 ? WindowsInstallerConstants.MsidbCustomActionType64BitScript : 0;
205 type |= customActionTuple.TSAware ? WindowsInstallerConstants.MsidbCustomActionTypeTSAware : 0;
206 type |= customActionTuple.Impersonate ? 0 : WindowsInstallerConstants.MsidbCustomActionTypeNoImpersonate;
207 type |= customActionTuple.IgnoreResult ? WindowsInstallerConstants.MsidbCustomActionTypeContinue : 0;
208 type |= customActionTuple.Hidden ? WindowsInstallerConstants.MsidbCustomActionTypeHideTarget : 0;
209 type |= customActionTuple.Async ? WindowsInstallerConstants.MsidbCustomActionTypeAsync : 0;
210 type |= CustomActionExecutionType.FirstSequence == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeFirstSequence : 0;
211 type |= CustomActionExecutionType.OncePerProcess == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeOncePerProcess : 0;
212 type |= CustomActionExecutionType.ClientRepeat == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeClientRepeat : 0;
213 type |= CustomActionExecutionType.Deferred == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript : 0;
214 type |= CustomActionExecutionType.Rollback == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeRollback : 0;
215 type |= CustomActionExecutionType.Commit == customActionTuple.ExecutionType ? WindowsInstallerConstants.MsidbCustomActionTypeInScript | WindowsInstallerConstants.MsidbCustomActionTypeCommit : 0;
216 type |= CustomActionSourceType.File == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeSourceFile : 0;
217 type |= CustomActionSourceType.Directory == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeDirectory : 0;
218 type |= CustomActionSourceType.Property == customActionTuple.SourceType ? WindowsInstallerConstants.MsidbCustomActionTypeProperty : 0;
219 type |= CustomActionTargetType.Dll == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeDll : 0;
220 type |= CustomActionTargetType.Exe == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeExe : 0;
221 type |= CustomActionTargetType.TextData == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeTextData : 0;
222 type |= CustomActionTargetType.JScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeJScript : 0;
223 type |= CustomActionTargetType.VBScript == customActionTuple.TargetType ? WindowsInstallerConstants.MsidbCustomActionTypeVBScript : 0;
224
225 fields = String.Join(",",
226 type.ToString(),
227 customActionTuple.Source,
228 customActionTuple.Target,
229 customActionTuple.PatchUninstall ? WindowsInstallerConstants.MsidbCustomActionTypePatchUninstall.ToString() : null
230 );
231 break;
232 }
233 case "Directory":
234 {
235 var directoryTuple = (DirectoryTuple)tuple;
248 236
249 case "RemoveRegistry": 237 if (!String.IsNullOrEmpty(directoryTuple.ComponentGuidGenerationSeed))
250 { 238 {
251 var removeRegistryTuple = (RemoveRegistryTuple)tuple; 239 yield return $"WixDirectory:{directoryTuple.Id.Id},{directoryTuple.ComponentGuidGenerationSeed}";
252 fields = String.Join(",",
253 ((int)removeRegistryTuple.Root).ToString(),
254 removeRegistryTuple.Key,
255 removeRegistryTuple.Name,
256 removeRegistryTuple.Component_
257 );
258 break;
259 } 240 }
260 241
261 case "ServiceControl": 242 fields = String.Join(",", directoryTuple.ParentDirectoryRef, directoryTuple.Name, directoryTuple.ShortName, directoryTuple.SourceName, directoryTuple.SourceShortName);
262 { 243 break;
263 var serviceControlTuple = (ServiceControlTuple)tuple; 244 }
264 245 case "Feature":
265 var events = serviceControlTuple.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0; 246 {
266 events |= serviceControlTuple.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0; 247 var featureTuple = (FeatureTuple)tuple;
267 events |= serviceControlTuple.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0; 248 var attributes = featureTuple.DisallowAbsent ? WindowsInstallerConstants.MsidbFeatureAttributesUIDisallowAbsent : 0;
268 events |= serviceControlTuple.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0; 249 attributes |= featureTuple.DisallowAdvertise ? WindowsInstallerConstants.MsidbFeatureAttributesDisallowAdvertise : 0;
269 events |= serviceControlTuple.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0; 250 attributes |= FeatureInstallDefault.FollowParent == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFollowParent : 0;
270 events |= serviceControlTuple.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0; 251 attributes |= FeatureInstallDefault.Source == featureTuple.InstallDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorSource : 0;
271 252 attributes |= FeatureTypicalDefault.Advertise == featureTuple.TypicalDefault ? WindowsInstallerConstants.MsidbFeatureAttributesFavorAdvertise : 0;
272 fields = String.Join(",", 253
273 serviceControlTuple.Name, 254 fields = String.Join(",",
274 events.ToString(), 255 featureTuple.ParentFeatureRef,
275 serviceControlTuple.Arguments, 256 featureTuple.Title,
276 serviceControlTuple.Wait == true ? "1" : "0", 257 featureTuple.Description,
277 serviceControlTuple.Component_ 258 featureTuple.Display.ToString(),
278 ); 259 featureTuple.Level.ToString(),
279 break; 260 featureTuple.DirectoryRef,
280 } 261 attributes.ToString());
262 break;
263 }
264 case "File":
265 {
266 var fileTuple = (FileTuple)tuple;
281 267
282 case "ServiceInstall": 268 if (fileTuple.BindPath != null)
283 { 269 {
284 var serviceInstallTuple = (ServiceInstallTuple)tuple; 270 yield return $"BindImage:{fileTuple.Id.Id},{fileTuple.BindPath}";
285
286 var errorControl = (int)serviceInstallTuple.ErrorControl;
287 errorControl |= serviceInstallTuple.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0;
288
289 var serviceType = (int)serviceInstallTuple.ServiceType;
290 serviceType |= serviceInstallTuple.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0;
291
292 fields = String.Join(",",
293 serviceInstallTuple.Name,
294 serviceInstallTuple.DisplayName,
295 serviceType.ToString(),
296 ((int)serviceInstallTuple.StartType).ToString(),
297 errorControl.ToString(),
298 serviceInstallTuple.LoadOrderGroup,
299 serviceInstallTuple.Dependencies,
300 serviceInstallTuple.StartName,
301 serviceInstallTuple.Password,
302 serviceInstallTuple.Arguments,
303 serviceInstallTuple.Component_,
304 serviceInstallTuple.Description
305 );
306 break;
307 } 271 }
308 272
309 case "Upgrade": 273 if (fileTuple.FontTitle != null)
310 { 274 {
311 var upgradeTuple = (UpgradeTuple)tuple; 275 yield return $"Font:{fileTuple.Id.Id},{fileTuple.FontTitle}";
312
313 var attributes = upgradeTuple.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0;
314 attributes |= upgradeTuple.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0;
315 attributes |= upgradeTuple.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0;
316 attributes |= upgradeTuple.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0;
317 attributes |= upgradeTuple.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0;
318 attributes |= upgradeTuple.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0;
319
320 fields = String.Join(",",
321 upgradeTuple.VersionMin,
322 upgradeTuple.VersionMax,
323 upgradeTuple.Language,
324 attributes.ToString(),
325 upgradeTuple.Remove,
326 upgradeTuple.ActionProperty
327 );
328 break;
329 } 276 }
330 277
331 case "WixAction": 278 if (fileTuple.SelfRegCost.HasValue)
332 { 279 {
333 var wixActionTuple = (WixActionTuple)tuple; 280 yield return $"SelfReg:{fileTuple.Id.Id},{fileTuple.SelfRegCost}";
334 fields = String.Join(",",
335 wixActionTuple.SequenceTable,
336 wixActionTuple.Action,
337 wixActionTuple.Condition,
338 // BUGBUGBUG: AB#2626
339 wixActionTuple.Sequence == 0 ? String.Empty : wixActionTuple.Sequence.ToString(),
340 wixActionTuple.Before,
341 wixActionTuple.After,
342 wixActionTuple.Overridable == true ? "1" : "0"
343 );
344 break;
345 } 281 }
346 282
347 case "WixComplexReference": 283 fields = String.Join(",",
348 { 284 fileTuple.ComponentRef,
349 var wixComplexReferenceTuple = (WixComplexReferenceTuple)tuple; 285 fileTuple.Name,
350 fields = String.Join(",", 286 fileTuple.FileSize.ToString(),
351 wixComplexReferenceTuple.Parent, 287 fileTuple.Version,
352 ((int)wixComplexReferenceTuple.ParentType).ToString(), 288 fileTuple.Language,
353 wixComplexReferenceTuple.ParentLanguage, 289 ((fileTuple.ReadOnly ? WindowsInstallerConstants.MsidbFileAttributesReadOnly : 0)
354 wixComplexReferenceTuple.Child, 290 | (fileTuple.Hidden ? WindowsInstallerConstants.MsidbFileAttributesHidden : 0)
355 ((int)wixComplexReferenceTuple.ChildType).ToString(), 291 | (fileTuple.System ? WindowsInstallerConstants.MsidbFileAttributesSystem : 0)
356 wixComplexReferenceTuple.IsPrimary ? "1" : "0" 292 | (fileTuple.Vital ? WindowsInstallerConstants.MsidbFileAttributesVital : 0)
357 ); 293 | (fileTuple.Checksum ? WindowsInstallerConstants.MsidbFileAttributesChecksum : 0)
358 break; 294 | ((fileTuple.Compressed.HasValue && fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesCompressed : 0)
359 } 295 | ((fileTuple.Compressed.HasValue && !fileTuple.Compressed.Value) ? WindowsInstallerConstants.MsidbFileAttributesNoncompressed : 0))
296 .ToString());
297 break;
298 }
360 299
361 case "WixFile": 300 case "Media":
362 { 301 fields = String.Join(",", tuple.Fields.Skip(1).Select(SafeConvertField));
363 var wixFileTuple = (WixFileTuple)tuple; 302 break;
364 fields = String.Concat( 303
365 wixFileTuple.AssemblyType == FileAssemblyType.DotNetAssembly ? "0" : wixFileTuple.AssemblyType == FileAssemblyType.Win32Assembly ? "1" : String.Empty, ",", 304 case "Registry":
366 String.Join(",", tuple.Fields.Skip(2).Take(6).Select(field => (string)field).ToArray())); 305 {
367 break; 306 var registryTuple = (RegistryTuple)tuple;
368 } 307 var value = registryTuple.Value;
369 308
370 case "WixProperty": 309 switch (registryTuple.ValueType)
371 { 310 {
372 var wixPropertyTuple = (WixPropertyTuple)tuple; 311 case RegistryValueType.Binary:
373 var attributes = 0; 312 value = String.Concat("#x", value);
374 attributes |= wixPropertyTuple.Admin ? 0x1 : 0; 313 break;
375 attributes |= wixPropertyTuple.Hidden ? 0x2 : 0; 314 case RegistryValueType.Expandable:
376 attributes |= wixPropertyTuple.Secure ? 0x4 : 0; 315 value = String.Concat("#%", value);
377 316 break;
378 fields = String.Join(",", 317 case RegistryValueType.Integer:
379 wixPropertyTuple.Property_, 318 value = String.Concat("#", value);
380 attributes.ToString() 319 break;
381 ); 320 case RegistryValueType.MultiString:
321 switch (registryTuple.ValueAction)
322 {
323 case RegistryValueActionType.Append:
324 value = String.Concat("[~]", value);
325 break;
326 case RegistryValueActionType.Prepend:
327 value = String.Concat(value, "[~]");
328 break;
329 case RegistryValueActionType.Write:
330 default:
331 if (null != value && -1 == value.IndexOf("[~]", StringComparison.Ordinal))
332 {
333 value = String.Concat("[~]", value, "[~]");
334 }
335 break;
336 }
337 break;
338 case RegistryValueType.String:
339 // escape the leading '#' character for string registry keys
340 if (null != value && value.StartsWith("#", StringComparison.Ordinal))
341 {
342 value = String.Concat("#", value);
343 }
382 break; 344 break;
383 } 345 }
384 346
347 fields = String.Join(",",
348 ((int)registryTuple.Root).ToString(),
349 registryTuple.Key,
350 registryTuple.Name,
351 value,
352 registryTuple.ComponentRef
353 );
354 break;
355 }
356
357 case "RemoveRegistry":
358 {
359 var removeRegistryTuple = (RemoveRegistryTuple)tuple;
360 fields = String.Join(",",
361 ((int)removeRegistryTuple.Root).ToString(),
362 removeRegistryTuple.Key,
363 removeRegistryTuple.Name,
364 removeRegistryTuple.ComponentRef
365 );
366 break;
367 }
368
369 case "ServiceControl":
370 {
371 var serviceControlTuple = (ServiceControlTuple)tuple;
372
373 var events = serviceControlTuple.InstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventDelete : 0;
374 events |= serviceControlTuple.UninstallRemove ? WindowsInstallerConstants.MsidbServiceControlEventUninstallDelete : 0;
375 events |= serviceControlTuple.InstallStart ? WindowsInstallerConstants.MsidbServiceControlEventStart : 0;
376 events |= serviceControlTuple.UninstallStart ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStart : 0;
377 events |= serviceControlTuple.InstallStop ? WindowsInstallerConstants.MsidbServiceControlEventStop : 0;
378 events |= serviceControlTuple.UninstallStop ? WindowsInstallerConstants.MsidbServiceControlEventUninstallStop : 0;
379
380 fields = String.Join(",",
381 serviceControlTuple.Name,
382 events.ToString(),
383 serviceControlTuple.Arguments,
384 serviceControlTuple.Wait == true ? "1" : "0",
385 serviceControlTuple.ComponentRef
386 );
387 break;
388 }
389
390 case "ServiceInstall":
391 {
392 var serviceInstallTuple = (ServiceInstallTuple)tuple;
393
394 var errorControl = (int)serviceInstallTuple.ErrorControl;
395 errorControl |= serviceInstallTuple.Vital ? WindowsInstallerConstants.MsidbServiceInstallErrorControlVital : 0;
396
397 var serviceType = (int)serviceInstallTuple.ServiceType;
398 serviceType |= serviceInstallTuple.Interactive ? WindowsInstallerConstants.MsidbServiceInstallInteractive : 0;
399
400 fields = String.Join(",",
401 serviceInstallTuple.Name,
402 serviceInstallTuple.DisplayName,
403 serviceType.ToString(),
404 ((int)serviceInstallTuple.StartType).ToString(),
405 errorControl.ToString(),
406 serviceInstallTuple.LoadOrderGroup,
407 serviceInstallTuple.Dependencies,
408 serviceInstallTuple.StartName,
409 serviceInstallTuple.Password,
410 serviceInstallTuple.Arguments,
411 serviceInstallTuple.ComponentRef,
412 serviceInstallTuple.Description
413 );
414 break;
415 }
416
417 case "Upgrade":
418 {
419 var upgradeTuple = (UpgradeTuple)tuple;
420
421 var attributes = upgradeTuple.MigrateFeatures ? WindowsInstallerConstants.MsidbUpgradeAttributesMigrateFeatures : 0;
422 attributes |= upgradeTuple.OnlyDetect ? WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect : 0;
423 attributes |= upgradeTuple.IgnoreRemoveFailures ? WindowsInstallerConstants.MsidbUpgradeAttributesIgnoreRemoveFailure : 0;
424 attributes |= upgradeTuple.VersionMinInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive : 0;
425 attributes |= upgradeTuple.VersionMaxInclusive ? WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive : 0;
426 attributes |= upgradeTuple.ExcludeLanguages ? WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive : 0;
427
428 fields = String.Join(",",
429 upgradeTuple.VersionMin,
430 upgradeTuple.VersionMax,
431 upgradeTuple.Language,
432 attributes.ToString(),
433 upgradeTuple.Remove,
434 upgradeTuple.ActionProperty
435 );
436 break;
437 }
438
439 case "WixAction":
440 {
441 var wixActionTuple = (WixActionTuple)tuple;
442 var data = wixActionTuple.Fields[(int)WixActionTupleFields.SequenceTable].AsObject();
443 var sequenceTableAsInt = data is string ? (int)SequenceStringToSequenceTable(data) : (int)wixActionTuple.SequenceTable;
444
445 fields = String.Join(",",
446 sequenceTableAsInt,
447 wixActionTuple.Action,
448 wixActionTuple.Condition,
449 wixActionTuple.Sequence?.ToString() ?? String.Empty,
450 wixActionTuple.Before,
451 wixActionTuple.After,
452 wixActionTuple.Overridable == true ? "1" : "0"
453 );
454 break;
455 }
456
457 case "WixComplexReference":
458 {
459 var wixComplexReferenceTuple = (WixComplexReferenceTuple)tuple;
460 fields = String.Join(",",
461 wixComplexReferenceTuple.Parent,
462 (int)wixComplexReferenceTuple.ParentType,
463 wixComplexReferenceTuple.ParentLanguage,
464 wixComplexReferenceTuple.Child,
465 (int)wixComplexReferenceTuple.ChildType,
466 wixComplexReferenceTuple.IsPrimary ? "1" : "0"
467 );
468 break;
469 }
470
471 case "WixFile":
472 {
473 var wixFileTuple = (WixFileTuple)tuple;
474 fields = String.Concat(
475 wixFileTuple.AssemblyType == FileAssemblyType.DotNetAssembly ? "0" : wixFileTuple.AssemblyType == FileAssemblyType.Win32Assembly ? "1" : String.Empty, ",",
476 String.Join(",", tuple.Fields.Skip(1).Take(8).Select(field => (string)field)));
477 break;
478 }
479
480 case "WixProperty":
481 {
482 var wixPropertyTuple = (WixPropertyTuple)tuple;
483 var attributes = wixPropertyTuple.Admin ? 0x1 : 0;
484 attributes |= wixPropertyTuple.Hidden ? 0x2 : 0;
485 attributes |= wixPropertyTuple.Secure ? 0x4 : 0;
486
487 fields = String.Join(",",
488 wixPropertyTuple.PropertyRef,
489 attributes.ToString()
490 );
491 break;
492 }
493
494 default:
495 fields = String.Join(",", tuple.Fields.Select(SafeConvertField));
496 break;
497 }
498
499 var name = tuple.Definition.Type == TupleDefinitionType.SummaryInformation ? "_SummaryInformation" : tuple.Definition.Name;
500 var id = tuple.Id?.Id ?? String.Empty;
501 fields = String.IsNullOrEmpty(id) ? fields : String.IsNullOrEmpty(fields) ? id : $"{id},{fields}";
502 yield return $"{name}:{fields}";
503 }
504
505 private static SequenceTable SequenceStringToSequenceTable(object sequenceString)
506 {
507 switch (sequenceString)
508 {
509 case "AdminExecuteSequence":
510 return SequenceTable.AdminExecuteSequence;
511 case "AdminUISequence":
512 return SequenceTable.AdminUISequence;
513 case "AdvtExecuteSequence":
514 return SequenceTable.AdvertiseExecuteSequence;
515 case "InstallExecuteSequence":
516 return SequenceTable.InstallExecuteSequence;
517 case "InstallUISequence":
518 return SequenceTable.InstallUISequence;
519 default:
520 throw new ArgumentException($"Unknown sequence: {sequenceString}");
385 } 521 }
522 }
386 523
387 var id = tuple.Id == null ? String.Empty : String.Concat(",", tuple.Id.Id); 524 private static string SafeConvertField(Wix3.Field field)
388 return $"{tuple.Definition.Name}{id},{fields}"; 525 {
526 return field?.Data?.ToString();
527 }
528
529 private static string SafeConvertField(IntermediateField field)
530 {
531 var data = field.AsObject();
532 if (data is IntermediateFieldPathValue path)
533 {
534 return path.Path;
535 }
536
537 return data?.ToString();
538 }
539
540 private static string[] SplitDefaultDir(string defaultDir)
541 {
542 var split1 = defaultDir.Split(':');
543 var targetSplit = split1.Length > 1 ? split1[1].Split('|') : split1[0].Split('|');
544 var sourceSplit = split1.Length > 1 ? split1[0].Split('|') : new[] { String.Empty };
545 return new[]
546 {
547 targetSplit.Length > 1 ? targetSplit[1] : targetSplit[0],
548 targetSplit.Length > 1 ? targetSplit[0] : String.Empty,
549 sourceSplit.Length > 1 ? sourceSplit[1] : sourceSplit[0],
550 sourceSplit.Length > 1 ? sourceSplit[0] : String.Empty
551 };
389 } 552 }
390 } 553 }
391} 554}