diff options
Diffstat (limited to 'src/WixToolset.Core/Bind/Bundles/ProcessMsiPackageCommand.cs')
-rw-r--r-- | src/WixToolset.Core/Bind/Bundles/ProcessMsiPackageCommand.cs | 560 |
1 files changed, 0 insertions, 560 deletions
diff --git a/src/WixToolset.Core/Bind/Bundles/ProcessMsiPackageCommand.cs b/src/WixToolset.Core/Bind/Bundles/ProcessMsiPackageCommand.cs deleted file mode 100644 index f73776c0..00000000 --- a/src/WixToolset.Core/Bind/Bundles/ProcessMsiPackageCommand.cs +++ /dev/null | |||
@@ -1,560 +0,0 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Bind.Bundles | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections; | ||
7 | using System.Collections.Generic; | ||
8 | using System.Diagnostics; | ||
9 | using System.Globalization; | ||
10 | using System.IO; | ||
11 | using System.Linq; | ||
12 | using WixToolset.Data; | ||
13 | using WixToolset.Data.Rows; | ||
14 | using WixToolset.Extensibility; | ||
15 | using WixToolset.Msi; | ||
16 | using WixToolset.Core.Native; | ||
17 | using Dtf = WixToolset.Dtf.WindowsInstaller; | ||
18 | |||
19 | /// <summary> | ||
20 | /// Initializes package state from the MSI contents. | ||
21 | /// </summary> | ||
22 | internal class ProcessMsiPackageCommand : ICommand | ||
23 | { | ||
24 | private const string PropertySqlFormat = "SELECT `Value` FROM `Property` WHERE `Property` = '{0}'"; | ||
25 | |||
26 | public RowDictionary<WixBundlePayloadRow> AuthoredPayloads { private get; set; } | ||
27 | |||
28 | public PackageFacade Facade { private get; set; } | ||
29 | |||
30 | public IBinderFileManager FileManager { private get; set; } | ||
31 | |||
32 | public Table MsiFeatureTable { private get; set; } | ||
33 | |||
34 | public Table MsiPropertyTable { private get; set; } | ||
35 | |||
36 | public Table PayloadTable { private get; set; } | ||
37 | |||
38 | public Table RelatedPackageTable { private get; set; } | ||
39 | |||
40 | /// <summary> | ||
41 | /// Processes the MSI packages to add properties and payloads from the MSI packages. | ||
42 | /// </summary> | ||
43 | public void Execute() | ||
44 | { | ||
45 | WixBundlePayloadRow packagePayload = this.AuthoredPayloads.Get(this.Facade.Package.PackagePayload); | ||
46 | |||
47 | string sourcePath = packagePayload.FullFileName; | ||
48 | bool longNamesInImage = false; | ||
49 | bool compressed = false; | ||
50 | bool x64 = false; | ||
51 | try | ||
52 | { | ||
53 | // Read data out of the msi database... | ||
54 | using (Dtf.SummaryInfo sumInfo = new Dtf.SummaryInfo(sourcePath, false)) | ||
55 | { | ||
56 | // 1 is the Word Count summary information stream bit that means | ||
57 | // the MSI uses short file names when set. We care about long file | ||
58 | // names so check when the bit is not set. | ||
59 | longNamesInImage = 0 == (sumInfo.WordCount & 1); | ||
60 | |||
61 | // 2 is the Word Count summary information stream bit that means | ||
62 | // files are compressed in the MSI by default when the bit is set. | ||
63 | compressed = 2 == (sumInfo.WordCount & 2); | ||
64 | |||
65 | x64 = (sumInfo.Template.Contains("x64") || sumInfo.Template.Contains("Intel64")); | ||
66 | |||
67 | // 8 is the Word Count summary information stream bit that means | ||
68 | // "Elevated privileges are not required to install this package." | ||
69 | // in MSI 4.5 and below, if this bit is 0, elevation is required. | ||
70 | this.Facade.Package.PerMachine = (0 == (sumInfo.WordCount & 8)) ? YesNoDefaultType.Yes : YesNoDefaultType.No; | ||
71 | this.Facade.Package.x64 = x64 ? YesNoType.Yes : YesNoType.No; | ||
72 | } | ||
73 | |||
74 | using (Dtf.Database db = new Dtf.Database(sourcePath)) | ||
75 | { | ||
76 | this.Facade.MsiPackage.ProductCode = ProcessMsiPackageCommand.GetProperty(db, "ProductCode"); | ||
77 | this.Facade.MsiPackage.UpgradeCode = ProcessMsiPackageCommand.GetProperty(db, "UpgradeCode"); | ||
78 | this.Facade.MsiPackage.Manufacturer = ProcessMsiPackageCommand.GetProperty(db, "Manufacturer"); | ||
79 | this.Facade.MsiPackage.ProductLanguage = Convert.ToInt32(ProcessMsiPackageCommand.GetProperty(db, "ProductLanguage"), CultureInfo.InvariantCulture); | ||
80 | this.Facade.MsiPackage.ProductVersion = ProcessMsiPackageCommand.GetProperty(db, "ProductVersion"); | ||
81 | |||
82 | if (!Common.IsValidModuleOrBundleVersion(this.Facade.MsiPackage.ProductVersion)) | ||
83 | { | ||
84 | // not a proper .NET version (e.g., five fields); can we get a valid four-part version number? | ||
85 | string version = null; | ||
86 | string[] versionParts = this.Facade.MsiPackage.ProductVersion.Split('.'); | ||
87 | int count = versionParts.Length; | ||
88 | if (0 < count) | ||
89 | { | ||
90 | version = versionParts[0]; | ||
91 | for (int i = 1; i < 4 && i < count; ++i) | ||
92 | { | ||
93 | version = String.Concat(version, ".", versionParts[i]); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | if (!String.IsNullOrEmpty(version) && Common.IsValidModuleOrBundleVersion(version)) | ||
98 | { | ||
99 | Messaging.Instance.OnMessage(WixWarnings.VersionTruncated(this.Facade.Package.SourceLineNumbers, this.Facade.MsiPackage.ProductVersion, sourcePath, version)); | ||
100 | this.Facade.MsiPackage.ProductVersion = version; | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | Messaging.Instance.OnMessage(WixErrors.InvalidProductVersion(this.Facade.Package.SourceLineNumbers, this.Facade.MsiPackage.ProductVersion, sourcePath)); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | if (String.IsNullOrEmpty(this.Facade.Package.CacheId)) | ||
109 | { | ||
110 | this.Facade.Package.CacheId = String.Format("{0}v{1}", this.Facade.MsiPackage.ProductCode, this.Facade.MsiPackage.ProductVersion); | ||
111 | } | ||
112 | |||
113 | if (String.IsNullOrEmpty(this.Facade.Package.DisplayName)) | ||
114 | { | ||
115 | this.Facade.Package.DisplayName = ProcessMsiPackageCommand.GetProperty(db, "ProductName"); | ||
116 | } | ||
117 | |||
118 | if (String.IsNullOrEmpty(this.Facade.Package.Description)) | ||
119 | { | ||
120 | this.Facade.Package.Description = ProcessMsiPackageCommand.GetProperty(db, "ARPCOMMENTS"); | ||
121 | } | ||
122 | |||
123 | ISet<string> payloadNames = this.GetPayloadTargetNames(); | ||
124 | |||
125 | ISet<string> msiPropertyNames = this.GetMsiPropertyNames(); | ||
126 | |||
127 | this.SetPerMachineAppropriately(db, sourcePath); | ||
128 | |||
129 | // Ensure the MSI package is appropriately marked visible or not. | ||
130 | this.SetPackageVisibility(db, msiPropertyNames); | ||
131 | |||
132 | // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance. | ||
133 | if (!msiPropertyNames.Contains("MSIFASTINSTALL") && !ProcessMsiPackageCommand.HasProperty(db, "MSIFASTINSTALL")) | ||
134 | { | ||
135 | this.AddMsiProperty("MSIFASTINSTALL", "7"); | ||
136 | } | ||
137 | |||
138 | this.CreateRelatedPackages(db); | ||
139 | |||
140 | // If feature selection is enabled, represent the Feature table in the manifest. | ||
141 | if (this.Facade.MsiPackage.EnableFeatureSelection) | ||
142 | { | ||
143 | this.CreateMsiFeatures(db); | ||
144 | } | ||
145 | |||
146 | // Add all external cabinets as package payloads. | ||
147 | this.ImportExternalCabinetAsPayloads(db, packagePayload, payloadNames); | ||
148 | |||
149 | // Add all external files as package payloads and calculate the total install size as the rollup of | ||
150 | // File table's sizes. | ||
151 | this.Facade.Package.InstallSize = this.ImportExternalFileAsPayloadsAndReturnInstallSize(db, packagePayload, longNamesInImage, compressed, payloadNames); | ||
152 | |||
153 | // Add all dependency providers from the MSI. | ||
154 | this.ImportDependencyProviders(db); | ||
155 | } | ||
156 | } | ||
157 | catch (Dtf.InstallerException e) | ||
158 | { | ||
159 | Messaging.Instance.OnMessage(WixErrors.UnableToReadPackageInformation(this.Facade.Package.SourceLineNumbers, sourcePath, e.Message)); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | private ISet<string> GetPayloadTargetNames() | ||
164 | { | ||
165 | IEnumerable<string> payloadNames = this.PayloadTable.RowsAs<WixBundlePayloadRow>() | ||
166 | .Where(r => r.Package == this.Facade.Package.WixChainItemId) | ||
167 | .Select(r => r.Name); | ||
168 | |||
169 | return new HashSet<string>(payloadNames, StringComparer.OrdinalIgnoreCase); | ||
170 | } | ||
171 | |||
172 | private ISet<string> GetMsiPropertyNames() | ||
173 | { | ||
174 | IEnumerable<string> properties = this.MsiPropertyTable.RowsAs<WixBundleMsiPropertyRow>() | ||
175 | .Where(r => r.ChainPackageId == this.Facade.Package.WixChainItemId) | ||
176 | .Select(r => r.Name); | ||
177 | |||
178 | return new HashSet<string>(properties, StringComparer.Ordinal); | ||
179 | } | ||
180 | |||
181 | private void SetPerMachineAppropriately(Dtf.Database db, string sourcePath) | ||
182 | { | ||
183 | if (this.Facade.MsiPackage.ForcePerMachine) | ||
184 | { | ||
185 | if (YesNoDefaultType.No == this.Facade.Package.PerMachine) | ||
186 | { | ||
187 | Messaging.Instance.OnMessage(WixWarnings.PerUserButForcingPerMachine(this.Facade.Package.SourceLineNumbers, sourcePath)); | ||
188 | this.Facade.Package.PerMachine = YesNoDefaultType.Yes; // ensure that we think the package is per-machine. | ||
189 | } | ||
190 | |||
191 | // Force ALLUSERS=1 via the MSI command-line. | ||
192 | this.AddMsiProperty("ALLUSERS", "1"); | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | string allusers = ProcessMsiPackageCommand.GetProperty(db, "ALLUSERS"); | ||
197 | |||
198 | if (String.IsNullOrEmpty(allusers)) | ||
199 | { | ||
200 | // Not forced per-machine and no ALLUSERS property, flip back to per-user. | ||
201 | if (YesNoDefaultType.Yes == this.Facade.Package.PerMachine) | ||
202 | { | ||
203 | Messaging.Instance.OnMessage(WixWarnings.ImplicitlyPerUser(this.Facade.Package.SourceLineNumbers, sourcePath)); | ||
204 | this.Facade.Package.PerMachine = YesNoDefaultType.No; | ||
205 | } | ||
206 | } | ||
207 | else if (allusers.Equals("1", StringComparison.Ordinal)) | ||
208 | { | ||
209 | if (YesNoDefaultType.No == this.Facade.Package.PerMachine) | ||
210 | { | ||
211 | Messaging.Instance.OnMessage(WixErrors.PerUserButAllUsersEquals1(this.Facade.Package.SourceLineNumbers, sourcePath)); | ||
212 | } | ||
213 | } | ||
214 | else if (allusers.Equals("2", StringComparison.Ordinal)) | ||
215 | { | ||
216 | Messaging.Instance.OnMessage(WixWarnings.DiscouragedAllUsersValue(this.Facade.Package.SourceLineNumbers, sourcePath, (YesNoDefaultType.Yes == this.Facade.Package.PerMachine) ? "machine" : "user")); | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | Messaging.Instance.OnMessage(WixErrors.UnsupportedAllUsersValue(this.Facade.Package.SourceLineNumbers, sourcePath, allusers)); | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | |||
225 | private void SetPackageVisibility(Dtf.Database db, ISet<string> msiPropertyNames) | ||
226 | { | ||
227 | bool alreadyVisible = !ProcessMsiPackageCommand.HasProperty(db, "ARPSYSTEMCOMPONENT"); | ||
228 | |||
229 | if (alreadyVisible != this.Facade.Package.Visible) // if not already set to the correct visibility. | ||
230 | { | ||
231 | // If the authoring specifically added "ARPSYSTEMCOMPONENT", don't do it again. | ||
232 | if (!msiPropertyNames.Contains("ARPSYSTEMCOMPONENT")) | ||
233 | { | ||
234 | this.AddMsiProperty("ARPSYSTEMCOMPONENT", this.Facade.Package.Visible ? String.Empty : "1"); | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | |||
239 | private void CreateRelatedPackages(Dtf.Database db) | ||
240 | { | ||
241 | // Represent the Upgrade table as related packages. | ||
242 | if (db.Tables.Contains("Upgrade")) | ||
243 | { | ||
244 | using (Dtf.View view = db.OpenView("SELECT `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes` FROM `Upgrade`")) | ||
245 | { | ||
246 | view.Execute(); | ||
247 | while (true) | ||
248 | { | ||
249 | using (Dtf.Record record = view.Fetch()) | ||
250 | { | ||
251 | if (null == record) | ||
252 | { | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | WixBundleRelatedPackageRow related = (WixBundleRelatedPackageRow)this.RelatedPackageTable.CreateRow(this.Facade.Package.SourceLineNumbers); | ||
257 | related.ChainPackageId = this.Facade.Package.WixChainItemId; | ||
258 | related.Id = record.GetString(1); | ||
259 | related.MinVersion = record.GetString(2); | ||
260 | related.MaxVersion = record.GetString(3); | ||
261 | related.Languages = record.GetString(4); | ||
262 | |||
263 | int attributes = record.GetInteger(5); | ||
264 | related.OnlyDetect = (attributes & MsiInterop.MsidbUpgradeAttributesOnlyDetect) == MsiInterop.MsidbUpgradeAttributesOnlyDetect; | ||
265 | related.MinInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesVersionMinInclusive) == MsiInterop.MsidbUpgradeAttributesVersionMinInclusive; | ||
266 | related.MaxInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive) == MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive; | ||
267 | related.LangInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesLanguagesExclusive) == 0; | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | |||
274 | private void CreateMsiFeatures(Dtf.Database db) | ||
275 | { | ||
276 | if (db.Tables.Contains("Feature")) | ||
277 | { | ||
278 | using (Dtf.View featureView = db.OpenView("SELECT `Component_` FROM `FeatureComponents` WHERE `Feature_` = ?")) | ||
279 | using (Dtf.View componentView = db.OpenView("SELECT `FileSize` FROM `File` WHERE `Component_` = ?")) | ||
280 | { | ||
281 | using (Dtf.Record featureRecord = new Dtf.Record(1)) | ||
282 | using (Dtf.Record componentRecord = new Dtf.Record(1)) | ||
283 | { | ||
284 | using (Dtf.View allFeaturesView = db.OpenView("SELECT * FROM `Feature`")) | ||
285 | { | ||
286 | allFeaturesView.Execute(); | ||
287 | |||
288 | while (true) | ||
289 | { | ||
290 | using (Dtf.Record allFeaturesResultRecord = allFeaturesView.Fetch()) | ||
291 | { | ||
292 | if (null == allFeaturesResultRecord) | ||
293 | { | ||
294 | break; | ||
295 | } | ||
296 | |||
297 | string featureName = allFeaturesResultRecord.GetString(1); | ||
298 | |||
299 | // Calculate the Feature size. | ||
300 | featureRecord.SetString(1, featureName); | ||
301 | featureView.Execute(featureRecord); | ||
302 | |||
303 | // Loop over all the components for the feature to calculate the size of the feature. | ||
304 | long size = 0; | ||
305 | while (true) | ||
306 | { | ||
307 | using (Dtf.Record componentResultRecord = featureView.Fetch()) | ||
308 | { | ||
309 | if (null == componentResultRecord) | ||
310 | { | ||
311 | break; | ||
312 | } | ||
313 | string component = componentResultRecord.GetString(1); | ||
314 | componentRecord.SetString(1, component); | ||
315 | componentView.Execute(componentRecord); | ||
316 | |||
317 | while (true) | ||
318 | { | ||
319 | using (Dtf.Record fileResultRecord = componentView.Fetch()) | ||
320 | { | ||
321 | if (null == fileResultRecord) | ||
322 | { | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | string fileSize = fileResultRecord.GetString(1); | ||
327 | size += Convert.ToInt32(fileSize, CultureInfo.InvariantCulture.NumberFormat); | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | |||
333 | WixBundleMsiFeatureRow feature = (WixBundleMsiFeatureRow)this.MsiFeatureTable.CreateRow(this.Facade.Package.SourceLineNumbers); | ||
334 | feature.ChainPackageId = this.Facade.Package.WixChainItemId; | ||
335 | feature.Name = featureName; | ||
336 | feature.Parent = allFeaturesResultRecord.GetString(2); | ||
337 | feature.Title = allFeaturesResultRecord.GetString(3); | ||
338 | feature.Description = allFeaturesResultRecord.GetString(4); | ||
339 | feature.Display = allFeaturesResultRecord.GetInteger(5); | ||
340 | feature.Level = allFeaturesResultRecord.GetInteger(6); | ||
341 | feature.Directory = allFeaturesResultRecord.GetString(7); | ||
342 | feature.Attributes = allFeaturesResultRecord.GetInteger(8); | ||
343 | feature.Size = size; | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | |||
352 | private void ImportExternalCabinetAsPayloads(Dtf.Database db, WixBundlePayloadRow packagePayload, ISet<string> payloadNames) | ||
353 | { | ||
354 | if (db.Tables.Contains("Media")) | ||
355 | { | ||
356 | foreach (string cabinet in db.ExecuteStringQuery("SELECT `Cabinet` FROM `Media`")) | ||
357 | { | ||
358 | if (!String.IsNullOrEmpty(cabinet) && !cabinet.StartsWith("#", StringComparison.Ordinal)) | ||
359 | { | ||
360 | // If we didn't find the Payload as an existing child of the package, we need to | ||
361 | // add it. We expect the file to exist on-disk in the same relative location as | ||
362 | // the MSI expects to find it... | ||
363 | string cabinetName = Path.Combine(Path.GetDirectoryName(packagePayload.Name), cabinet); | ||
364 | |||
365 | if (!payloadNames.Contains(cabinetName)) | ||
366 | { | ||
367 | string generatedId = Common.GenerateIdentifier("cab", packagePayload.Id, cabinet); | ||
368 | string payloadSourceFile = FileManager.ResolveRelatedFile(packagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.Facade.Package.SourceLineNumbers, BindStage.Normal); | ||
369 | |||
370 | WixBundlePayloadRow payload = (WixBundlePayloadRow)this.PayloadTable.CreateRow(this.Facade.Package.SourceLineNumbers); | ||
371 | payload.Id = generatedId; | ||
372 | payload.Name = cabinetName; | ||
373 | payload.SourceFile = payloadSourceFile; | ||
374 | payload.Compressed = packagePayload.Compressed; | ||
375 | payload.UnresolvedSourceFile = cabinetName; | ||
376 | payload.Package = packagePayload.Package; | ||
377 | payload.Container = packagePayload.Container; | ||
378 | payload.ContentFile = true; | ||
379 | payload.EnableSignatureValidation = packagePayload.EnableSignatureValidation; | ||
380 | payload.Packaging = packagePayload.Packaging; | ||
381 | payload.ParentPackagePayload = packagePayload.Id; | ||
382 | } | ||
383 | } | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | |||
388 | private long ImportExternalFileAsPayloadsAndReturnInstallSize(Dtf.Database db, WixBundlePayloadRow packagePayload, bool longNamesInImage, bool compressed, ISet<string> payloadNames) | ||
389 | { | ||
390 | long size = 0; | ||
391 | |||
392 | if (db.Tables.Contains("Component") && db.Tables.Contains("Directory") && db.Tables.Contains("File")) | ||
393 | { | ||
394 | Hashtable directories = new Hashtable(); | ||
395 | |||
396 | // Load up the directory hash table so we will be able to resolve source paths | ||
397 | // for files in the MSI database. | ||
398 | using (Dtf.View view = db.OpenView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) | ||
399 | { | ||
400 | view.Execute(); | ||
401 | while (true) | ||
402 | { | ||
403 | using (Dtf.Record record = view.Fetch()) | ||
404 | { | ||
405 | if (null == record) | ||
406 | { | ||
407 | break; | ||
408 | } | ||
409 | |||
410 | string sourceName = Installer.GetName(record.GetString(3), true, longNamesInImage); | ||
411 | directories.Add(record.GetString(1), new ResolvedDirectory(record.GetString(2), sourceName)); | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | |||
416 | // Resolve the source paths to external files and add each file size to the total | ||
417 | // install size of the package. | ||
418 | using (Dtf.View view = db.OpenView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`")) | ||
419 | { | ||
420 | view.Execute(); | ||
421 | while (true) | ||
422 | { | ||
423 | using (Dtf.Record record = view.Fetch()) | ||
424 | { | ||
425 | if (null == record) | ||
426 | { | ||
427 | break; | ||
428 | } | ||
429 | |||
430 | // Skip adding the loose files as payloads if it was suppressed. | ||
431 | if (!this.Facade.MsiPackage.SuppressLooseFilePayloadGeneration) | ||
432 | { | ||
433 | // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not | ||
434 | // explicitly marked compressed then this is an external file. | ||
435 | if (MsiInterop.MsidbFileAttributesNoncompressed == (record.GetInteger(4) & MsiInterop.MsidbFileAttributesNoncompressed) || | ||
436 | (!compressed && 0 == (record.GetInteger(4) & MsiInterop.MsidbFileAttributesCompressed))) | ||
437 | { | ||
438 | string fileSourcePath = Binder.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage); | ||
439 | string name = Path.Combine(Path.GetDirectoryName(packagePayload.Name), fileSourcePath); | ||
440 | |||
441 | if (!payloadNames.Contains(name)) | ||
442 | { | ||
443 | string generatedId = Common.GenerateIdentifier("f", packagePayload.Id, record.GetString(2)); | ||
444 | string payloadSourceFile = FileManager.ResolveRelatedFile(packagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.Facade.Package.SourceLineNumbers, BindStage.Normal); | ||
445 | |||
446 | WixBundlePayloadRow payload = (WixBundlePayloadRow)this.PayloadTable.CreateRow(this.Facade.Package.SourceLineNumbers); | ||
447 | payload.Id = generatedId; | ||
448 | payload.Name = name; | ||
449 | payload.SourceFile = payloadSourceFile; | ||
450 | payload.Compressed = packagePayload.Compressed; | ||
451 | payload.UnresolvedSourceFile = name; | ||
452 | payload.Package = packagePayload.Package; | ||
453 | payload.Container = packagePayload.Container; | ||
454 | payload.ContentFile = true; | ||
455 | payload.EnableSignatureValidation = packagePayload.EnableSignatureValidation; | ||
456 | payload.Packaging = packagePayload.Packaging; | ||
457 | payload.ParentPackagePayload = packagePayload.Id; | ||
458 | } | ||
459 | } | ||
460 | } | ||
461 | |||
462 | size += record.GetInteger(5); | ||
463 | } | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | |||
468 | return size; | ||
469 | } | ||
470 | |||
471 | private void AddMsiProperty(string name, string value) | ||
472 | { | ||
473 | WixBundleMsiPropertyRow row = (WixBundleMsiPropertyRow)this.MsiPropertyTable.CreateRow(this.Facade.MsiPackage.SourceLineNumbers); | ||
474 | row.ChainPackageId = this.Facade.Package.WixChainItemId; | ||
475 | row.Name = name; | ||
476 | row.Value = value; | ||
477 | } | ||
478 | |||
479 | private void ImportDependencyProviders(Dtf.Database db) | ||
480 | { | ||
481 | if (db.Tables.Contains("WixDependencyProvider")) | ||
482 | { | ||
483 | string query = "SELECT `ProviderKey`, `Version`, `DisplayName`, `Attributes` FROM `WixDependencyProvider`"; | ||
484 | |||
485 | using (Dtf.View view = db.OpenView(query)) | ||
486 | { | ||
487 | view.Execute(); | ||
488 | while (true) | ||
489 | { | ||
490 | using (Dtf.Record record = view.Fetch()) | ||
491 | { | ||
492 | if (null == record) | ||
493 | { | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | // Import the provider key and attributes. | ||
498 | string providerKey = record.GetString(1); | ||
499 | string version = record.GetString(2) ?? this.Facade.MsiPackage.ProductVersion; | ||
500 | string displayName = record.GetString(3) ?? this.Facade.Package.DisplayName; | ||
501 | int attributes = record.GetInteger(4); | ||
502 | |||
503 | ProvidesDependency dependency = new ProvidesDependency(providerKey, version, displayName, attributes); | ||
504 | dependency.Imported = true; | ||
505 | |||
506 | this.Facade.Provides.Add(dependency); | ||
507 | } | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | } | ||
512 | |||
513 | /// <summary> | ||
514 | /// Queries a Windows Installer database for a Property value. | ||
515 | /// </summary> | ||
516 | /// <param name="db">Database to query.</param> | ||
517 | /// <param name="property">Property to examine.</param> | ||
518 | /// <returns>String value for result or null if query doesn't match a single result.</returns> | ||
519 | private static string GetProperty(Dtf.Database db, string property) | ||
520 | { | ||
521 | try | ||
522 | { | ||
523 | return db.ExecuteScalar(PropertyQuery(property)).ToString(); | ||
524 | } | ||
525 | catch (Dtf.InstallerException) | ||
526 | { | ||
527 | } | ||
528 | |||
529 | return null; | ||
530 | } | ||
531 | |||
532 | /// <summary> | ||
533 | /// Queries a Windows Installer database to determine if one or more rows exist in the Property table. | ||
534 | /// </summary> | ||
535 | /// <param name="db">Database to query.</param> | ||
536 | /// <param name="property">Property to examine.</param> | ||
537 | /// <returns>True if query matches at least one result.</returns> | ||
538 | private static bool HasProperty(Dtf.Database db, string property) | ||
539 | { | ||
540 | try | ||
541 | { | ||
542 | return 0 < db.ExecuteQuery(PropertyQuery(property)).Count; | ||
543 | } | ||
544 | catch (Dtf.InstallerException) | ||
545 | { | ||
546 | } | ||
547 | |||
548 | return false; | ||
549 | } | ||
550 | |||
551 | private static string PropertyQuery(string property) | ||
552 | { | ||
553 | // quick sanity check that we'll be creating a valid query... | ||
554 | // TODO: Are there any other special characters we should be looking for? | ||
555 | Debug.Assert(!property.Contains("'")); | ||
556 | |||
557 | return String.Format(CultureInfo.InvariantCulture, ProcessMsiPackageCommand.PropertySqlFormat, property); | ||
558 | } | ||
559 | } | ||
560 | } | ||