main
cs 135 lines 6.29 KB
Raw
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.Core.WindowsInstaller
4 {
5 using System;
6 using System.IO;
7 using System.Linq;
8 using WixToolset.Core.WindowsInstaller.Bind;
9 using WixToolset.Core.WindowsInstaller.Decompile;
10 using WixToolset.Core.WindowsInstaller.Unbind;
11 using WixToolset.Data;
12 using WixToolset.Data.WindowsInstaller;
13 using WixToolset.Extensibility;
14 using WixToolset.Extensibility.Data;
15 using WixToolset.Extensibility.Services;
16
17 /// <summary>
18 /// Decompiler of the WiX toolset.
19 /// </summary>
20 internal class WindowsInstallerDecompiler : IWindowsInstallerDecompiler
21 {
22 internal WindowsInstallerDecompiler(IServiceProvider serviceProvider)
23 {
24 this.ServiceProvider = serviceProvider;
25 this.Messaging = serviceProvider.GetService<IMessaging>();
26 this.ExtensionManager = serviceProvider.GetService<IExtensionManager>();
27 }
28
29 private IServiceProvider ServiceProvider { get; }
30
31 private IMessaging Messaging { get; }
32
33 private IExtensionManager ExtensionManager { get; }
34
35 public IWindowsInstallerDecompileResult Decompile(IWindowsInstallerDecompileContext context)
36 {
37 if (context.SymbolDefinitionCreator == null)
38 {
39 context.SymbolDefinitionCreator = this.ServiceProvider.GetService<ISymbolDefinitionCreator>();
40 }
41
42 var decompilerHelper = context.ServiceProvider.GetService<IWindowsInstallerDecompilerHelper>();
43
44 // Pre-decompile.
45 //
46 foreach (var extension in context.Extensions)
47 {
48 extension.PreDecompile(context, decompilerHelper);
49 }
50
51 // Decompile.
52 //
53 var result = this.Execute(context, decompilerHelper);
54
55 if (result != null)
56 {
57 // Post-decompile.
58 //
59 foreach (var extension in context.Extensions)
60 {
61 extension.PostDecompile(result);
62 }
63 }
64
65 return result;
66 }
67
68 private IWindowsInstallerDecompileResult Execute(IWindowsInstallerDecompileContext context, IWindowsInstallerDecompilerHelper decompilerHelper)
69 {
70 // Delete the directory and its files to prevent cab extraction failure due to an existing file.
71 if (!String.IsNullOrEmpty(context.ExtractFolder) && Directory.Exists(context.ExtractFolder))
72 {
73 Directory.Delete(context.ExtractFolder, true);
74 }
75
76 var backendHelper = context.ServiceProvider.GetService<IWindowsInstallerBackendHelper>();
77
78 var fileSystem = context.ServiceProvider.GetService<IFileSystem>();
79
80 var pathResolver = context.ServiceProvider.GetService<IPathResolver>();
81
82 if (context.DecompileType == OutputType.Transform)
83 {
84 return this.DecompileTransform(context, backendHelper, fileSystem, pathResolver);
85 }
86 else
87 {
88 return this.DecompileDatabase(context, decompilerHelper, backendHelper, fileSystem, pathResolver);
89 }
90 }
91
92 private IWindowsInstallerDecompileResult DecompileDatabase(IWindowsInstallerDecompileContext context, IWindowsInstallerDecompilerHelper decompilerHelper, IWindowsInstallerBackendHelper backendHelper, IFileSystem fileSystem, IPathResolver pathResolver)
93 {
94 var extractFilesFolder = context.SuppressExtractCabinets || (String.IsNullOrEmpty(context.CabinetExtractFolder) && String.IsNullOrEmpty(context.ExtractFolder)) ? null :
95 String.IsNullOrEmpty(context.CabinetExtractFolder) ? Path.Combine(context.ExtractFolder, "File") : context.CabinetExtractFolder;
96
97 var demodularize = !context.KeepModularizationIds;
98 var sectionType = context.DecompileType;
99 var unbindCommand = new UnbindDatabaseCommand(this.Messaging, backendHelper, fileSystem, pathResolver, context.DecompilePath, null, sectionType, context.ExtractFolder, extractFilesFolder, context.IntermediateFolder, demodularize, skipSummaryInfo: false);
100 var output = unbindCommand.Execute();
101 var extractedFilePaths = unbindCommand.ExportedFiles;
102
103 var decompiler = new Decompiler(this.Messaging, backendHelper, decompilerHelper, context.Extensions, context.ExtensionData, context.SymbolDefinitionCreator, context.BaseSourcePath, context.SuppressCustomTables, context.SuppressDroppingEmptyTables, context.SuppressRelativeActionSequencing, context.SuppressUI, context.KeepModularizationIds);
104 var document = decompiler.Decompile(output);
105
106 var result = context.ServiceProvider.GetService<IWindowsInstallerDecompileResult>();
107 result.Data = output;
108 result.Document = document;
109 result.Platform = GetPlatformFromOutput(output);
110 result.ExtractedFilePaths = extractedFilePaths.ToList();
111 return result;
112 }
113
114 private IWindowsInstallerDecompileResult DecompileTransform(IWindowsInstallerDecompileContext context, IWindowsInstallerBackendHelper backendHelper, IFileSystem fileSystem, IPathResolver pathResolver)
115 {
116 var fileSystemExtensions = this.ExtensionManager.GetServices<IFileSystemExtension>();
117
118 var fileSystemManager = new FileSystemManager(fileSystem, fileSystemExtensions);
119
120 var unbindCommand = new UnbindTransformCommand(this.Messaging, backendHelper, fileSystem, pathResolver, fileSystemManager, context.DecompilePath, context.ExtractFolder, context.IntermediateFolder);
121 var output = unbindCommand.Execute();
122
123 var result = context.ServiceProvider.GetService<IWindowsInstallerDecompileResult>();
124 result.Data = output;
125 return result;
126 }
127
128 private static Platform? GetPlatformFromOutput(WindowsInstallerData output)
129 {
130 var template = output.Tables["_SummaryInformation"]?.Rows.SingleOrDefault(row => row.FieldAsInteger(0) == 7)?.FieldAsString(1);
131
132 return Decompiler.GetPlatformFromTemplateSummaryInformation(template?.Split(';'));
133 }
134 }
135 }